当涉及到核心数据 - 每个线程有一个托管对象上下文时,有一条黄金法则。被管对象上下文不是线程安全的,所以如果你在后台任务中工作,你可以使用主线程来避免线程与UI操作的冲突,或者你创建一个新的上下文来完成工作。如果工作要做几秒钟后,你应该做后者来阻止你的用户界面锁定。
要做到这一点,你创建一个新的上下文,并给它相同的持久性存储作为你的主要方面:
NSManagedObjectContext *backgroundContext = [[[NSManagedObjectContext alloc] init] autorelease];
[backgroundContext setPersistentStoreCoordinator:[mainContext persistentStoreCoordinator]];
什么就做什么业务,你需要做的,那么当你保存新的环境下,你需要处理保存通知并将更改合并到mergeChangesFromContextDidSaveNotification:
消息的主要上下文中。代码应该是这个样子:
/* Save notification handler for the background context */
- (void)backgroundContextDidSave:(NSNotification *)notification {
/* Make sure we're on the main thread when updating the main context */
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
withObject:notification
waitUntilDone:NO];
return;
}
/* merge in the changes to the main context */
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
/* ... */
/* Save the background context and handle the save notification */
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(backgroundContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:backgroundContext];
[backgroundContext save:NULL];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:syncContext];
处理保存notifcation和合并是很重要的,否则你的主UI /上下文将不会看到你所做的更改。通过合并,您的主要fetchResultsController等将获得更改事件并按照您的预期更新您的UI。
另一个需要注意的重要的事情是,NSManagedObject实例只能在它们被提取的上下文中使用。如果您的操作需要对对象的引用,那么您必须将该对象的objectID
传递给该操作,并使用existingObjectWithID:
从新的上下文中重新获取NSManagedObject实例。所以像这样:
/* This can only be used in operations on the main context */
MyNSManagedObject *objectInMainContext =
[self.fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
/* This can now be used in your background context */
MyNSManagedObject *objectInBackgroundContext =
(MyNSManagedObject *) [backgroundContext existingObjectWithID:[objectInMainContext objectID]];
所以,你说的是,在我的情况下,而不是使用fetchedResultsController,我应该创建一个新的托管对象上下文(backgro如何获取所需的托管对象,执行所需操作,更新托管对象,保存托管对象上下文(backgroundManagedObjectContext),然后合并更改以反映在主托管对象上下文中?这会让我的生活非常痛苦。 – Mustafa 2010-11-24 08:54:07