我有一堆NSOperations需要在队列中运行时创建和获取实体。
在NSOperations中创建实体时,我可以简单地使用默认上下文创建,或者因为我在主线程上没有新线程,这是不允许/建议的?如果我在这个线程上创建一个新实体,那么将它合并回默认上下文的最佳方法是什么(而不是保存到商店)?
在获取这些线程时,我需要获取然后更新该实体中的数据。我不知道如何做到这一点然后合并到默认上下文。
或者,当您保存时,您获取/创建的线程是否真的无关紧要?
我说上面的默认上下文是因为我有NSFetchedResultsControllers监视更新和插入的默认上下文。目前我的解决方案是在主线程上完成所有这些工作,但是应用程序现在开始爬行,现在正在通过它运行大量数据。
我还有一个类监控(通过KVO)操作队列计数。一旦它变为零,我就预先形成一个保存。我宁愿只在完成所有上述NSOperations后执行,就像我现在正在执行的那样。谢谢你的帮助。
答案 0 :(得分:8)
现在让我们忽略MagicalRecord。要在多个线程上使用Core Data,您需要了解一些事项。
NSManagedObject
。相反,传递所需对象的NSManagedObjectID
,然后在后台线程中重新获取它。NSManagedObjectContext
。这意味着您必须了解initWithConcurrencyType:
的含义。我们将进入那个。主线程
您的主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;
}
后台主题
每当你在后台线程中工作时,你需要启动一个新的上下文。您不应该在线程之间共享上下文。将对主线程上下文的引用传递到操作中,并在操作开始后构建后台上下文。这将确保它构建在您将执行工作的线程上。
- (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
,但由于您尚未调用save,因此数据尚未保留。在队列KVO中,您可以通过排队保存块来调用主上下文中的保存。
[self performBlock:^{
NSError *error;
[self save:&error];
if (error) {
// handle errors
}
}];