提前感谢任何帮助。我今天花了很多时间与此作斗争,我认为我对框架运作方式的理解存在严重问题。
我正在开发一个核心数据应用程序,其中实体具有父/子关系。应用程序在启动时创建NSManagedObjectContext(MOC)。当应用程序第一次运行时,它使用异步块将plist的内容导入第二个MOC(根节点是使用URI和-managedObjectIDForURIRepresentation :)从主MOC获取的,就在块完成之前保存第二个上下文。
在我的数据控制器中,我订阅了NSManagedObjectContextDidSaveNotification,并在发送通知时运行以下代码:
- (void)backgroundContextDidSave:(NSNotification *)notification {
if(![notification.object isEqual:self.managedObjectContext]){
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
withObject:notification
waitUntilDone:NO];
return;
}
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification]; ;
}
}
我对这段代码进行了一次完整性检查,当然,当第二个MOC保存时,从执行块的线程调用它,然后延迟,并从主线程运行。通知对象包含在第二个MOC中导入的所有对象,包括我们接下来要处理的两个对象。
当这个完成后,我运行以下代码,该代码位于对象所属的NSManagedObject子类的方法中,它只是意味着从子代中删除子代:
TreeEntry *oldParent=self.parent; //keep a pointer to the old parent around so we can delete self from the children
// These next four lines are a sanity check to make sure that both objects are on the same MOC we're saving
NSManagedObjectContext *selfContext=self.managedObjectContext;
NSManagedObjectContext *parentContext=self.parent.managedObjectContext;
NSManagedObjectContext *sharedContext=[[DataController sharedDataController] managedObjectContext];
assert([selfContext isEqual:parentContext] && [selfContext isEqual:sharedContext]);
// now we fault the two objects to make sure we can not possibly have them or any changes
// to them in the state of the main MOC, by this time the second MOC is long gone
[sharedContext refreshObject:self.parent mergeChanges:NO];
[sharedContext refreshObject:self mergeChanges:NO];
// up to this point, sharedContex.insertedObjects, sharedContext.updatedObects and sharedContext.deletedObjects
// have all contained no objects at all. None of the above was necessary as the MOC held no changes at all
[sharedContext saveChanges]; // we save it to, well, just to make sure I guess, I may be going crazy
// Now we carry out two changes to the objects, problem occurs if only one change is carried out,
// I'm showing both to show that there relationship is being kept consistent and valid
self.parent=nil;
[oldParent removeChild:self];
// When the next line is run the save fails with a merge conflict
[sharedContext saveChanges];
最后一次保存失败,出现Cocoa错误133020,这是合并失败。错误中的两个NSMergeConflicts与我们正在处理的条目(self和self.parent)有关。
我只是不明白这是怎么回事。对象在被修改时没有状态,因此它们必须从商店加载。进行两个简单的更改,然后在直接保存它们之后发生合并冲突。怎么可能?没有别的东西搞砸了商店,我们只是加载了它的对象。
我知道我可以更改合并政策但我不想在不了解正在发生的情况下这样做。
有什么想法吗?我确信这只是我的心理模型,如果发生的事情是错误的,但我一直都没能把它整理好!
答案 0 :(得分:7)
好的,我对这个框架如何工作或者更准确的NSManagedStoreCoordinator缓存有一个根本的误解。
当我保存后台上下文时,更改将转到磁盘,但显然NSManagedStoreCoordinator(两个上下文共享)都不会更新或使其缓存无效。
当我刷新主MOC中的对象时,用于重新填充它们的数据来自缓存,缓存仍然具有旧数据。它不会从磁盘重新加载。解决方案是使用[MOC setStalenessInterval:0.0]强制从磁盘重新加载。