在后台队列中保存临时托管对象上下文
Posted
技术标签:
【中文标题】在后台队列中保存临时托管对象上下文【英文标题】:Saving a temporary managed object context on a background queue 【发布时间】:2013-10-29 01:01:58 【问题描述】:根据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];
];
);
);
【问题讨论】:
【参考方案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];
];
其次:
“在后台线程中保存容易出错”(据我所知并理解)意思是: 您可以在后台保存,但不保证您调用的保存会在应用程序退出时运行完成(数据库仍然有效,或者可以回滚到部分保存前的状态)。 ==> 如果您使用后台保存,请不要假设在 2 次应用程序执行之间保存操作已完成。
第三点(只是为了强调):
不要使用没有performBlock:
或performBlockAndWait:
的私有队列上下文
==>
您的第二个示例将导致意外行为
【讨论】:
好的,在 performBlock 中调用保存是有意义的,但是有没有办法确保在应用程序退出之前后台保存完全完成? 正如我在第二点中提到的那样,不。这就是主线程保存和后台保存的区别。如果您有必须保存的关键信息,请在主线程上进行。 谢谢,但我最初的问题是我该怎么做呢?你说我的第二个例子会导致意想不到的行为。是因为我没有使用 performBlock 还是因为它是在主线程上执行的私有队列上下文?请参阅我编辑的问题。在主线程上保存的正确方法是什么? 您的第二个示例是错误的,因为未在私有队列上下文performBlock...
方法中完成保存。用户可能随时终止您的应用程序,恕不另行通知(在后台)。这意味着所有未完成的保存都不会完成(主线程上的事件)。你应该保存在主线程的原因是为了给用户一个一致的体验(用户执行了一个永久效果的动作,这应该反映在下一次应用程序运行==>保存在主线程上)
好的,所以我的第二个示例现在是正确的,这样保存在主线程上执行并且将始终完成?以上是关于在后台队列中保存临时托管对象上下文的主要内容,如果未能解决你的问题,请参考以下文章