我如何将iCloud集成到我的AppDelegate?

时间:2014-08-03 13:29:45

标签: ios objective-c core-data icloud

我需要帮助将iCloud集成到我的CoreData中。 我在AppDelegate上尝试了很多更改,但只有错误:

  

“libc ++ abi.dylib:以NSException类型的未捕获异常终止”

我有一个TeamID和一个开发者帐户。

的AppDelegate:

//
//  AppDelegate.m
//  ToolDB
//
//  Created by Patrick Gottberg on 01.07.14.
//
//

#import "AppDelegate.h"

#import "PersonsTVC.h"
#import "RolePersonsTVC.h"
#import "MaterialPersonsTVC.h"
#import "RolesTVC.h"
#import "MaterialsTVC.h"
#import "PersonsTVC.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize managedObjectContext = __managedObjectContext;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
@synthesize fetchedResultsController = __fetchedResultsController;

- (void)insertRoleWithRoleName:(NSString *)roleName
{
    Role *role = [NSEntityDescription insertNewObjectForEntityForName:@"Role"
                                               inManagedObjectContext:self.managedObjectContext];

    role.name = roleName;        
    [self.managedObjectContext save:nil];
}

- (void)insertMaterialWithMaterialName:(NSString *)materialName
{
    Material *material = [NSEntityDescription insertNewObjectForEntityForName:@"Material"
                                                       inManagedObjectContext:self.managedObjectContext];

    material.name = materialName;

    [self.managedObjectContext save:nil];
}

- (void)insertPersonWithPersonfirstname:(NSString *)personfirstname
{
    Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person"
                                                   inManagedObjectContext:self.managedObjectContext];

    person.firstname = personfirstname ;
    person.surname= @"Example";
    [self.managedObjectContext save:nil];
}


- (void)importCoreDataDefaultRoles {

    NSLog(@"Importing Core Data Default Values for Roles...");
    [self insertRoleWithRoleName:@"DMG Mori DMU 70 "];
    [self insertRoleWithRoleName:@"Kunzmann BA 800"];
    NSLog(@"Importing Core Data Default Values for Roles Completed!");
}


- (void)importCoreDataDefaultMaterials {

    NSLog(@"Importing Core Data Default Values for Materials...");
    [self insertMaterialWithMaterialName:@"S235"];
    [self insertMaterialWithMaterialName:@"26Mo2"];
    [self insertMaterialWithMaterialName:@"1.2316"];
    [self insertMaterialWithMaterialName:@"C16"];

    NSLog(@"Importing Core Data Default Values for Materials Completed!");
}

- (void)importCoreDataDefaultPersons {

    NSLog(@"Importing Core Data Default Values for Persons...");
    [self insertPersonWithPersonfirstname:@"Square"];
    [self insertPersonWithPersonfirstname:@"T-Slot"];
    [self insertPersonWithPersonfirstname:@"Ball"];
    [self insertPersonWithPersonfirstname:@"Shell"];
    NSLog(@"Importing Core Data Default Values for Persons Completed!");

}


- (void)setupFetchedResultsController
{
    // 1 - Decide what Entity you want
    NSString *entityName = @"Role"; // Put your entity name here
    NSLog(@"Setting up a Fetched Results Controller for the Entity named %@", entityName);

    // 2 - Request that Entity
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];

    // 3 - Filter it if you want
    //request.predicate = [NSPredicate predicateWithFormat:@"Person.name = Blah"];

    // 4 - Sort it if you want
    request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name"
                                                                                     ascending:YES
                                                                                      selector:@selector(localizedCaseInsensitiveCompare:)]];
    // 5 - Fetch it
    self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                                                        managedObjectContext:self.managedObjectContext
                                                                          sectionNameKeyPath:nil
                                                                                   cacheName:nil];
    [self.fetchedResultsController performFetch:nil];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Set the application defaults
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"YES"
                                                            forKey:@"myKeyName"];
    [defaults registerDefaults:appDefaults];
    [defaults synchronize];

    [self setupFetchedResultsController];

    if (![[self.fetchedResultsController fetchedObjects] count] > 0 ) {
        NSLog(@"!!!!! ~~> There's nothing in the database so defaults will be inserted");
        [self importCoreDataDefaultRoles];
        [self importCoreDataDefaultMaterials];
        [self importCoreDataDefaultPersons];
    }
    else {
        NSLog(@"There's stuff in the database so skipping the import of default data");
    }

    // TAB BAR
    UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;

    // Override point for customization after application launch.
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {

        NSLog(@"I'm an iPad");

        // *** Set up the Persons Split Views (2-Way Delegation & Pass Managed Object Context) *** //

        // Set up SPLIT VIEW for Persons
        UISplitViewController *splitViewController = [[tabBarController viewControllers] objectAtIndex:0];

        // Set up Split View MASTER view for Persons
        UINavigationController *personsMasterTVCnav = [splitViewController.viewControllers objectAtIndex:0];
        splitViewController.delegate = (id)personsMasterTVCnav.topViewController;
        PersonsTVC *personsTVC = [[personsMasterTVCnav viewControllers] objectAtIndex:0];
        personsTVC.managedObjectContext = self.managedObjectContext;

        // Set up Split View DETAIL view for Persons
        UINavigationController *personsDetailTVCnav = [splitViewController.viewControllers objectAtIndex:1];
        PersonDetailTVC *personDetailTVC = [personsDetailTVCnav.viewControllers objectAtIndex:0];

        // Set up MASTER and DETAIL delegation so we can send messages between views
        personsTVC.delegate = personDetailTVC;
        personDetailTVC.delegate = personsTVC;

        // *** Set up the Roles Views *** (Pass Managed Object Context)//
        UINavigationController *rolesTVCnav = [[tabBarController viewControllers] objectAtIndex:1];
        RolesTVC *rolesTVC = [[rolesTVCnav viewControllers] objectAtIndex:0];
        rolesTVC.managedObjectContext = self.managedObjectContext;

        // *** Set up the Materials Views *** (Pass Managed Object Context)//
        UINavigationController *materialsTVCnav = [[tabBarController viewControllers] objectAtIndex:2];
        MaterialsTVC *materialsTVC = [[materialsTVCnav viewControllers] objectAtIndex:0];
        materialsTVC.managedObjectContext = self.managedObjectContext;

        // Set delegate for splitViewController
        splitViewController.delegate = personDetailTVC;


    }
    else
    {
        NSLog(@"I'm an iPhone or iPod Touch");

        // The Two Navigation Controllers attached to the Tab Bar (At Tab Bar Indexes 0 and 1)
        UINavigationController *personsTVCnav = [[tabBarController viewControllers] objectAtIndex:0];
        UINavigationController *rolesTVCnav = [[tabBarController viewControllers] objectAtIndex:1];
        UINavigationController *materialsTVCnav = [[tabBarController viewControllers] objectAtIndex:2];
        // The Persons Table View Controller (First Nav Controller Index 0)
        PersonsTVC *personsTVC = [[personsTVCnav viewControllers] objectAtIndex:0];
        personsTVC.managedObjectContext = self.managedObjectContext;


        // The Roles Table View Controller (Second Nav Controller Index 0)
        RolesTVC *rolesTVC = [[rolesTVCnav viewControllers] objectAtIndex:0];
        rolesTVC.managedObjectContext = self.managedObjectContext;

        // The Materials Table View Controller (Third Nav Controller Index 0)
        MaterialsTVC *materialsTVC = [[materialsTVCnav viewControllers] objectAtIndex:0];
        materialsTVC.managedObjectContext = self.managedObjectContext;
    }

    return YES;
}



- (void)applicationWillResignActive:(UIApplication *)application
{
    /*
     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
     */
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    /*
     Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
     If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
     */
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    /*
     Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
     */
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     */
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Saves changes in the application's managed object context before the application terminates.
    [self saveContext];
}

- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil)
    {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error])
        {
            /*
             Replace this implementation with code to handle the error appropriately.

             abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
             */
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

#pragma mark - Core Data stack

/**
 Returns the managed object context for the application.
 If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
 */
- (NSManagedObjectContext *)managedObjectContext
{
    if (__managedObjectContext != nil)
    {
        return __managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        __managedObjectContext = [[NSManagedObjectContext alloc] init];
        [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return __managedObjectContext;
}

/**
 Returns the managed object model for the application.
 If the model doesn't already exist, it is created from the application's model.
 */
- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil)
    {
        return __managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return __managedObjectModel;
}

/**
 Returns the persistent store coordinator for the application.
 If the coordinator doesn't already exist, it is created and the application's store added to it.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"StaffManager.sqlite"];

    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];


    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    {
        /*
         Replace this implementation with code to handle the error appropriately.

         abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

         Typical reasons for an error here include:
         * The persistent store is not accessible;
         * The schema for the persistent store is incompatible with current managed object model.
         Check the error message to determine what the actual problem was.


         If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.

         If you encounter schema incompatibility errors during development, you can reduce their frequency by:
         * Simply deleting the existing store:
         [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]

         * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
         [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

         Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

         */
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return __persistentStoreCoordinator;
}



#pragma mark - Application's Documents directory

/**
 Returns the URL to the application's Documents directory.
 */
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

@end

我有一个使用icloud的例子,但它是为ios5写的,我不知道我必须为ios7改变: 这就是AppDelegate中的icloud支持代码:

if((__persistentStoreCoordinator != nil)) {
        return __persistentStoreCoordinator;
    }

    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];    
    NSPersistentStoreCoordinator *psc = __persistentStoreCoordinator;

    // Set up iCloud in another thread:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // ** Note: if you adapt this code for your own use, you MUST change this variable:
        NSString *iCloudEnabledAppID = @"5KFJ75859U.Tim-Roadley.Staff-Manager";

        // ** Note: if you adapt this code for your own use, you should change this variable:        
        NSString *dataFileName = @"StaffManager.sqlite";

        // ** Note: For basic usage you shouldn't need to change anything else

        NSString *iCloudDataDirectoryName = @"Data.nosync";
        NSString *iCloudLogsDirectoryName = @"Logs";
        NSFileManager *fileManager = [NSFileManager defaultManager];        
        NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
        NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];

        if (iCloud) {

            NSLog(@"iCloud is working");

            NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];

            NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
            NSLog(@"dataFileName = %@", dataFileName); 
            NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName);
            NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName);  
            NSLog(@"iCloud = %@", iCloud);
            NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);

            if([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) {
                NSError *fileSystemError;
                [fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName] 
                       withIntermediateDirectories:YES 
                                        attributes:nil 
                                             error:&fileSystemError];
                if(fileSystemError != nil) {
                    NSLog(@"Error creating database directory %@", fileSystemError);
                }
            }

            NSString *iCloudData = [[[iCloud path] 
                                     stringByAppendingPathComponent:iCloudDataDirectoryName] 
                                    stringByAppendingPathComponent:dataFileName];

            NSLog(@"iCloudData = %@", iCloudData);

            NSMutableDictionary *options = [NSMutableDictionary dictionary];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
            [options setObject:iCloudEnabledAppID            forKey:NSPersistentStoreUbiquitousContentNameKey];
            [options setObject:iCloudLogsPath                forKey:NSPersistentStoreUbiquitousContentURLKey];

            [psc lock];

            [psc addPersistentStoreWithType:NSSQLiteStoreType 
                              configuration:nil 
                                        URL:[NSURL fileURLWithPath:iCloudData] 
                                    options:options 
                                      error:nil];

            [psc unlock];
        }
        else {
            NSLog(@"iCloud is NOT working - using a local store");
            NSMutableDictionary *options = [NSMutableDictionary dictionary];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
            [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];

            [psc lock];

            [psc addPersistentStoreWithType:NSSQLiteStoreType 
                              configuration:nil 
                                        URL:localStore 
                                    options:options 
                                      error:nil];
            [psc unlock];

        }

        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:@"SomethingChanged" object:self userInfo:nil];
        });
    });

    return __persistentStoreCoordinator;

我还有ManagedObjectContext的代码:

- (NSManagedObjectContext *)managedObjectContext {

    if (__managedObjectContext != nil) {
        return __managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

    if (coordinator != nil) {
        NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

        [moc performBlockAndWait:^{
            [moc setPersistentStoreCoordinator: coordinator];
            [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(mergeChangesFrom_iCloud:) name:NSPersistentStoreDidImportUbiquitousContentChangesNotification object:coordinator];
        }];
        __managedObjectContext = moc;
    }

    return __managedObjectContext;
}

- (void)mergeChangesFrom_iCloud:(NSNotification *)notification {

    NSLog(@"Merging in changes from iCloud...");

    NSManagedObjectContext* moc = [self managedObjectContext];

    [moc performBlock:^{

        [moc mergeChangesFromContextDidSaveNotification:notification]; 

        NSNotification* refreshNotification = [NSNotification notificationWithName:@"SomethingChanged"
                                                                            object:self
                                                                          userInfo:[notification userInfo]];

        [[NSNotificationCenter defaultCenter] postNotification:refreshNotification];
    }];
}

0 个答案:

没有答案