4

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

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

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

还是在保存时获取/创建哪个线程真的无关紧要?

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

另外我有一个类监控(通过KVO)操作队列计数。一旦它变为零,我就会进行保存。我宁愿只在上述所有 NSOperations 像我目前正在做的那样执行完之后才保存。感谢您的帮助。

4

1 回答 1

8

现在让我们忽略 MagicalRecord。要在多个线程上使用 Core Data,您需要注意一些事项。

  1. NSManagedObject永远不要在线程之间传递。相反,传递NSManagedObjectID你想要的对象,然后在你的后台线程中重新获取它。
  2. 负责任地构建您的NSManagedObjectContext. 这意味着你必须知道什么initWithConcurrencyType:意思。我们将深入探讨。

主线程

您的 mainNSManagedObjectContext应该使用并发类型构建NSMainQueueConcurrencyType。这将允许您利用队列中内置的上下文来执行串行操作。每当后台线程与主上下文交互时,您都应该使用performBlockor来完成工作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;
}

后台线程

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

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

将此背景上下文视为便笺簿。无论您在那里做什么,都会一直留在那里,直到您保存为止。因为您设置了 parentContext,所以在后台上下文中保存会将更改合并到您的主上下文中。这将更新NSFetchedResultsController,但由于您尚未调用保存,因此数据尚未持久化。在您的队列 KVO 中,您可以通过排队保存块来调用主上下文的保存。

[self performBlock:^{
    NSError *error;
    [self save:&error];
    if (error) {
        // handle errors
    }
}];
于 2013-07-23T15:56:31.190 回答