當涉及到核心數據 - 每個線程有一個託管對象上下文時,有一條黃金法則。被管對象上下文不是線程安全的,所以如果你在後臺任務中工作,你可以使用主線程來避免線程與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