Magical Record在单独的线程中创建/获取实体

ink*_*002 4 core-data nsoperation nsmanagedobjectcontext ios magicalrecord

我有一堆NSOperations需要在队列中运行时创建和获取实体.

  1. 在NSOperations中创建实体时,我可以简单地使用默认上下文创建,或者因为我在不在主线程上的新线程中是不允许/建议的?如果我在这个线程上创建一个新实体,那么将它合并回默认上下文然后(而不是保存到商店)的最佳方法是什么?

  2. 在获取这些线程时,我需要获取然后更新该实体中的数据.我不知道如何做到这一点然后合并到默认上下文.

或者,当您保存时,您获取/创建的线程真的无关紧要?

我说上面的默认上下文,因为我有NSFetchedResultsControllers监视更新和插入的默认上下文.目前我的解决方案是在主线程上完成所有这些工作,但是应用程序现在开始爬行,现在正在通过它运行大量数据.

我还有一个类监控(通过KVO)操作队列计数.一旦它变为零,我就预先形成一个保存.我宁愿只在完成所有上述NSOperations后执行,就像我现在正在执行的那样.感谢您的帮助.

Dre*_*its 8

我们暂时忽略MagicalRecord.要在多个线程上使用Core Data,您需要了解一些事情.

  1. 永远不要NSManagedObject在线程之间传递.相反,传递NSManagedObjectID所需的对象,并在后台线程中重新获取它.
  2. 负责任地建立你的NSManagedObjectContext.这意味着你必须知道什么initWithConcurrencyType:意思.我们将进入那个.

主线程

您的main NSManagedObjectContext应该使用并发类型构建NSMainQueueConcurrencyType.这将允许您利用内置队列中的上下文来执行串行操作.每当后台线程与主上下文交互时,您应该使用performBlock或执行工作performBlockAndWait.

- (NSManagedObjectContext *)managedObjectContext 
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }

    return _managedObjectContext;
}
Run Code Online (Sandbox Code Playgroud)

背景线程

无论何时在后台线程中工作,都需要启动新的上下文.您不应该在线程之间共享上下文.将对主线程上下文的引用传递到操作中,并在操作开始后构建后台上下文.这将确保它构建在您将执行工作的线程上.

- (NSManagedObjectContext *)newBackgroundManagedObjectContext
{    
    // Create new context with private concurrency type
    NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [newContext setParentContext:self.mainContext];

    // Optimization
    [newContext setUndoManager:nil];

    return newContext;
}
Run Code Online (Sandbox Code Playgroud)

将此背景上下文视为便笺簿.无论你做什么,都会留在那里,直到你拯救.由于您设置了parentContext,因此对背景上下文的保存会将更改合并到主上下文中.这将更新NSFetchedResultsController,但数据尚未保留,因为您没有调用save.在队列KVO中,您可以通过排队保存块来调用主上下文中的保存.

[self performBlock:^{
    NSError *error;
    [self save:&error];
    if (error) {
        // handle errors
    }
}];
Run Code Online (Sandbox Code Playgroud)