如何同时初始化Core Data堆栈?

时间:2014-05-05 21:02:13

标签: ios cocoa-touch

我是iOS编程的新手,我一直坚持使用GCD初始化Core Data堆栈。 我尝试过的(来自AppDelegate.m的代码):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
bgQueue = dispatch_queue_create("com.example.coredata.init", DISPATCH_QUEUE_SERIAL);
    dispatch_async(bgQueue, ^{
        NSPersistentStoreCoordinator *psc =  [self persistentStoreCoordinator];
        _managedObjectContext = [[NSManagedObjectContext alloc]  initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_managedObjectContext setPersistentStoreCoordinator:psc];
        dispatch_async(dispatch_get_main_queue(), ^{
            _mainThreadManagedObjectContext = [[NSManagedObjectContext alloc]  initWithConcurrencyType:NSMainQueueConcurrencyType];
            [_mainThreadManagedObjectContext setParentContext:_managedObjectContext];
            UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
            MasterViewController *controller = (MasterViewController *)navigationController.topViewController;
            controller.managedObjectContext = _mainThreadManagedObjectContext;
        });
    });
}

然而,dispatch_async(dispatch_get_main_queue())中的一个块没有执行,应用程序失败并出现错误" nil不是合法的NSManagedObjectContext参数"当应用程序的其他部分尝试使用NSManagedObjectContext时。

那么,我应该在哪里初始化Core Data对象?也许在MasterViewController中?或者可以等待NSManagedObjectContext初始化?谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

目前尚不清楚为什么要用这种方式使用GCD。我相信最常见的模式是懒散地设置核心数据堆栈,就像他们的大多数示例中的apple一样。如果在创建项目时选中“使用核心数据”框,则可以在主/明细项目的默认Xcode模板中看到它。

在AppDelegate中,您可以找到我粘贴在下面的代码。无论何时使用,都会设置堆栈。所以不需要与GCD异步。

 - (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:@"CoreDataStack" 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:@"CoreDataStack.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil 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:
         @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}

         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;
}

我还建议你看看这篇博文:https://www.cocoanetics.com/2012/07/multi-context-coredata/,它讨论了一种很好地构建核心数据堆栈的方法。它是一个很好的基础。 (参见建议堆栈的图片)enter image description here