我有一个我正在努力追查的错误。我相信正在发生的事情是我从底层数据库中删除一个对象,而另一个托管对象上下文(在另一个线程中)有一个错误,并在尝试完成错误时获得'NSObjectInaccessibleException'。
场景是我有一个视图通过一个上下文同时在后台访问数据,另一个威胁是从商店中清除过时的记录。后台线程应该只清除视图不需要的对象 - 显然情况并非如此,但我无法准确地追踪到底发生了什么。当我看到缺陷时,为时已晚,这是一个相对罕见的缺陷,主要发生在现场。
因此我的问题是:在调试CoreData时是否有任何技巧缺失 - 我可以在另一个上下文中跟踪对象的生命周期吗?即当我删除我的对象时,有一种简单的方法可以查看是否有任何其他上下文引用了同一个对象?使用它,我可以构建一些测试代码来检查我的逻辑并找到错误。
我之前遇到过这个错误,罪魁祸首是我正在清理(完成发布)我的上下文,然后尝试访问由该上下文管理的对象(以前)。
就我而言,上下文是一个“刮擦”上下文,在视图关闭时会消失。但是,我有一个后台工作,该视图产生了想要更新对象的后台工作。
我最终为[managedObject isFault]为true时返回nil的托管对象创建了一个访问器。然后在我的代码中,我检查了访问器选择器的值,以确保我有一个有效的对象(比如当我的后台作业最终完成它的工作)。
我对Core Data很陌生,所以可能有更好/更聪明的方法来做到这一点,但我认为它解决了我的问题。
我也只是面对这个问题。我做了一些重构来追随Apple的 “发现 - 或创建” 批量导入数据的模式。我通过将undomanager设置为nil来创建一个专用于导入的新上下文。
所以:
// create a new special context for the bulk import of data
NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] init];
[importContext setPersistentStoreCoordinator:_persistentStoreCoordinator];
// avoid tracking for undo/redo operations
[importContext setUndoManager:nil];
然后我创建了一个fetchRequest来检索存储在数据库中的对象的id,并且在import循环中我测试了对象的id以查找它是否包含在检索到的id数组中...问题是在给定的时间间隔我正在保存importContext并重置它。因为我错误地引用了importContext而不是defaultContext,所以我得到了那个错误。我只是通过改变来修复:
NSArray *storedObjects = [importContext executeFetchRequest:checkRequest error:&fetchError];
有:
NSArray *storedObjects = [defaultContext executeFetchRequest:checkRequest error:&fetchError];
当它试图在从持久性存储中删除的对象中出错时,第二个上下文是做什么的?
这听起来像一个可能包含两部分的错误:你没有合并来自你的对等上下文的更改,并且你有一个逻辑错误导致你在线程B中使用了一个已经在线程A中删除的对象。
通常,您希望使用以下方式合并来自对等上下文的更改 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:]
。
解决方案是清理和组合 这个mapkit错误。在我发布了NSManagedObjectContext之后,地图视图正在保持其委托。 Mapkit向代表询问了注释的坐标,我的委托对象试图查询处于已发布上下文中的对象(类似于Jason的问题)。
修复程序如Jake的博客文章中所述 - 当您完成地图视图时将委托设置为nil。