说我有 4 MOC (托管对象上下文),如下所示:
rootMOC (后台保存) - > fetchMOC (后台抓取) - > mainMOC (与UI相关)
rootMOC - > networkMOC (网络相关)
'A->B' means A is a parent of B.
所以工作流程是这样的:
[moc refreshObject :对象mergeChanges: YES ] mainMOC 进行更改[确定]
稍后我访问导致故障的对象属性同时在fetchMOC和mainMOC中触发 [轰隆,崩溃!]
我确定的事情:
以下是线程4中的代码崩溃( fetchMOC )
comparator = [^NSComparisonResult(id obj1, id obj2) {
ArticleInfo* info1 = obj1;
ArticleInfo* info2 = obj2;
if (info2.timeStamp > info1.timeStamp) { //[Thread4 fetchMOC:Crash]
return NSOrderedAscending;
}
else if (info2.timeStamp == info1.timeStamp) {
return NSOrderedSame;
}
else {
return NSOrderedDescending;
}
} copy];
同时在mainMOC中发生了什么:
[self.fetchMOC performBlock:^{
[self.fetchMOC refreshObject:self.currentUserFetchMOC mergeChanges:YES];
for (Stream* stream in self.currentUserFetchMOC.streams) {
[self.fetchMOC refreshObject:stream mergeChanges:YES];
}
[self.mainMOC performBlock:^{
LogMessage(@"MainMOC", 0, @"%@", @"Refresh steams Begin");
[self.mainMOC refreshObject:self.currentUserMainMOC mergeChanges:YES];
for (Stream* stream in self.currentUserMainMOC.streams) {
[self.mainMOC refreshObject:stream mergeChanges:YES];
if ([stream.uri isEqualToString:self.currentUserMainMOC.currentStreamURI]) {//Thread 1, here
self.currentStreamMainMOC = stream;
}
}
LogMessage(@"MainMOC", 0, @"%@", @"Refresh steams End");
}];
}];
修改:
为何失败:
在检查我的代码的每一行后,我找出原因。 我通过用existingObjectWithID替换objectWithID来检查,以确保对象已经存在于fetchMOC和mainMOC中。结果是一个惊喜,nowObjectWithID返回nil。所以我认为原因是[networkMOC save]没有保存所有同步,并且我不应该在保存返回后立即调用objectWithID。
解决方法:
我只是在调用[fetchMOC mergeChangesFromContextDidSaveNotification]之后立即将所有对象合并代码移动到 NSManagedObjectContextDidSaveNotification处理程序,这次existingObjectWithID返回有效对象并且不会再次崩溃。
仍然喜欢:
会话303 - iOS上核心数据的新功能告诉我,通过使用嵌套的MOC,我可以在兄弟MOC之间共享未保存的更改,这就是我试图实现的(我失败了)。据我所知,没有示例代码/博客/视频显示我在调用[sourceMOC save]之后要做什么,其中Apple人员只是通过访问托管对象的属性来“拉动”更改。通过访问属性显然无法正常工作! 使用mergeChangesFromContextDidSaveNotification时,它只是简单地太慢了。 我在开发论坛中创建了一个帖子,到目前为止都没有得到答案。
答案 0 :(得分:0)
召,
维持MOC之间的一致性可能很棘手。 MOC易于创建和销毁。持久性存储及其协调器旨在保持一致性。行缓存非常快。因此,我建议您根据需要创建和销毁MOC。我怀疑当你开始为每个后台操作使用新的MOC时,你的问题就会消失。 (在我的应用程序中,确实如此。)
安德鲁