调试NSObjectInaccessibleException - ID为0x123456789的NSManagedObject已失效

时间:2009-08-09 07:25:00

标签: core-data

我有一个我正在努力追查的错误。我相信正在发生的事情是我从底层数据库中删除一个对象,而另一个托管对象上下文(在另一个线程中)有一个错误,并在它尝试完成错误时获得'NSObjectInaccessibleException'。

场景是我有一个视图通过一个上下文同时在后台访问数据,另一个威胁是从商店中清除过时的记录。后台线程应该只清除视图不需要的对象 - 显然情况并非如此,但我无法准确地追踪到底发生了什么。当我看到缺陷时,为时已晚,这是一个相对罕见的缺陷,主要发生在现场。

因此我的问题是:调试CoreData时是否有任何技巧缺失 - 我可以在另一个上下文中跟踪对象的生命周期吗?即当我删除我的对象时,有一个简单的方法来查看是否有任何其他上下文具有对同一对象的引用?使用它,我可以构建一些测试代码来检查我的逻辑并找到错误。

4 个答案:

答案 0 :(得分:7)

我之前遇到过这个错误,罪魁祸首是我正在清理(已完成发布)我的上下文,然后尝试访问由该上下文管理的对象(以前)。

在我的情况下,上下文是一个“刮擦”上下文,在视图关闭时会消失。但是,我有一个后台工作,该视图产生了想要更新对象的视图。

当[managedObject isFault]为true时,我最终为托管对象创建了一个访问者,该访问者返回了nil。然后在我的代码中,我检查了访问器选择器的值,以确保我有一个有效的对象可以使用(例如当我的后台作业最终完成其工作时)。

我对核心数据很陌生,所以可能有更好/更聪明的方法来做到这一点,但我认为它解决了我的问题。

答案 1 :(得分:2)

我也只是面对这个问题。我做了一些重构,以遵循Apple的“find-or-create”模式进行批量导入数据。我通过将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];

答案 2 :(得分:1)

当它试图在从持久存储中删除的对象出错时,第二个上下文是做什么的?

这听起来像一个可能包含两部分的错误:你没有合并来自你的对等上下文的更改,并且你有一个逻辑错误导致你在线程B中使用一个已在线程A中删除的对象。

通常,您希望使用-[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:]合并来自对等上下文的更改。

答案 3 :(得分:1)

解决方案是清理和this mapkit bug的组合。在我发布了NSManagedObjectContext之后,地图视图正在抓住它的委托。 Mapkit向代表询问了注释的坐标,我的委托对象试图查询处于已发布上下文中的对象(类似于Jason的问题)。

修复程序如Jake的博文中所述 - 在完成地图视图后将委托设置为nil。