我正在开发一个应用程序,我需要在后台线程上计算事物(多秒操作)和写东西(与服务器同步数据)。
因此,我使用两个NSManagedObjectContexts(MOC),一个子节点和一个父节点,这些必须始终保持同步。为了确保它们是同步的,我总是编辑/添加数据给子MOC,以便它以下列模式被推送到主MOC:
[childMOC performBlock:^{
MyObject *myObject = *create new object in childMOC*
[childMOC save:&error];
[mainMOC performBlock:^{
[mainMOC save:&error];
// Is this mandatory to make it work correctly?
// [childMOC performBlock:^{
// [childMOC refreshObject:myObject mergeChanges:NO];
// }];
}];
}];
过了一会儿,我似乎在后台上下文中有两个版本的同一个对象,一个带有临时ID,另一个带有永久ID。如果我将子对象添加到“真实”对象(通过将新的永久ID从主MOC传递到子MOC)当我在后台MOC中检索到我的对象时,我没有看到这些对象,因为它是缓存的旧临时对象。
我已经看到上面的模式被大量使用,但似乎没有人提到这个临时/永久ID问题。
在上下文中它可以是同一对象的两个版本,这感觉不对。如果我将一个NSManagedObjectID传递给子MOC并检索它,那么子MOC是否应该更新我现有的对象而不是创建一个新对象并将我的旧临时对象保留为缓存默认值?
我是否需要在创建对象的每个地方使用注释行?
或许它可以与mergeChangesFromContextDidSaveNotification一起使用,会产生同样的效果吗?
答案 0 :(得分:3)
我的解决方案是:
1)使用背景MOC作为父MOC,使用主MOC作为孩子。作为奖励,我不需要保存主MOC来获取永久ID。
[DC.backgroundMOC performBlock:^{
// Add, save and update managed objects
[DC saveContext]; // The changes is being pushed to the main context
}];
2)使用NSManagedObjectContextDidSaveNotification使主MOC保持最新状态(主要MOC正在更新UI)
- (void) backgroundMOCSaved:(NSNotification*)notification {
[mainMOC performBlock:^{
[mainMOC mergeChangesFromContextDidSaveNotification:notification];
}];
}
答案 1 :(得分:1)
我遇到了这个问题并且解决方案是确保父MOC上的所有操作都使用performBlock:来完成,即使是初始设置:
parentManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[parentManagedObjectContext performBlock:^{
[parentManagedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[parentManagedObjectContext setPersistentStoreCoordinator:coordinator];
}];
一旦我这样做,我的孩子MOC就开始接受改变。