根据Concurrency with Core Data Guide,您不应该在后台线程中保存NSManagedObjectContext,因为应用程序可以在保存完成之前退出,因为线程已分离。
如果我理解正确,那就意味着这样的事情是不正确的
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSManagedObjectContext* tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[tempContext setParentContext:[[MyDataManager sharedInstance] mainContext];
[tempContext performBlockAndWait:^{
//Do some processing
NSError* error;
[tempContext save:&error];
}];
});
我的第一直觉是在主队列完成时将其保存在主队列中,但是managedObjectContexts应该是线程安全的。以下是解决问题的方法还是有更好的解决方案?
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSManagedObjectContext* tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[tempContext setParentContext:[[MyDataManager sharedInstance] mainContext];
[tempContext performBlockAndWait:^{
//Do some processing
}];
dispatch_async(dispatch_get_main_queue(), ^{
[tempContext performBlockAndWait:^{
NSError* error;
[tempContext save:&error];
}];
});
});
答案 0 :(得分:1)
第一:
在你的第一个例子中:
[context save:...]
应在上下文的performBlockAndWait:
块中完成
此外,如果您使用的是背景上下文,则可以简单地调用其performBlock:
方法,因为它已经使用GCD进行调度,因此它看起来像这样:
NSManagedObjectContext* tempContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[tempContext setParentContext:[[MyDataManager sharedInstance] mainContext];
[tempContext performBlock:^{
//Do some processing
NSError* error;
[tempContext save:&error];
}];
其次:
“在后台线程中保存容易出错”(据我所知并理解)意味着:
您可以在后台保存,但如果应用程序退出(数据库仍然有效,或者可以回滚到部分保存前状态),则无法保证您调用的保存将运行完成。 />
==>
如果使用后台保存,请不要假设在两次应用程序执行之间完成了保存操作。
第三(仅强调):
不要在没有performBlock:
或performBlockAndWait:
的情况下使用私有队列上下文
==>
你的第二个例子会导致意想不到的行为