根据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];
}];
});
});
最佳答案
第一:
在第一个示例中:
[context save:...]
应在上下文的 performBlockAndWait:
block 中完成。
另外,如果您使用后台上下文,您可以简单地调用其 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:
的私有(private)队列上下文
==>
你的第二个例子将导致意外的行为
关于ios - 在后台队列中保存临时管理对象上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19647854/