mergeChangesFromContextDidSaveNotification上的EXC_BAD_ACCESS

时间:2015-01-14 22:33:18

标签: ios objective-c core-data nsmanagedobjectcontext magicalrecord

我们一直在尝试调试Core Data多上下文/线程问题,其中将Core Data保存通知合并到我们的主线程NSManagedObjectContext中偶尔会使应用程序崩溃。这导致约2%的应用会话崩溃,我们对如何解决这个问题感到茫然。我们非常感谢任何可能导致此次崩溃的指导或一般性建议。

我们有一个核心数据设置,如下所示:

Core Data Stack N.B。这是从[MagicalRecord setupAutoMigratingCoreDataStack]创建的Magical Record v2.3中的默认核心数据堆栈

这是我们的应用崩溃的情况:

  1. HTTP请求返回JSON
  2. 根节省上下文
  3. 中将JSON解析为NSManagedObject s(一些新实体,一些更新的实体)
  4. 根节省上下文保存到持久存储
  5. NSManagedObjectContextDidSaveNotification由Core Data广播。主队列上的默认上下文会观察到此情况,并使用主线程上的mergeChangesFromContextDidSaveNotification:更改调用NSDictionary
  6. objectID被发送到无效对象时很可能崩溃(很可能NSManagedObject已被解除分配)。
  7. 这发生在NSManagedObjectContext mergeChangesFromContextDidSaveNotification:的私人实施中,所以我们不可能看到这里出了什么问题;在这一点上,我们只能说出一个应该存在的对象。

    enter image description here

    这仅发生在Core Data保存的一小部分上,表明这可能不是我们的Core Data→API堆栈的根本缺陷。此外,没有迹象表明上下文更改中的更改(插入/更新/删除)的大小或类型对崩溃的可能性有任何影响。

3 个答案:

答案 0 :(得分:4)

NSManagedObjectContextDidSaveNotification的文档说:

"您可以将通知对象传递给另一个线程上的mergeChangesFromContextDidSaveNotification:,但是您不能直接在另一个线程上使用用户信息字典中的托管对象。有关更多详细信息,请参阅“核心数据编程指南”中的“与核心数据的并发”。"

也许这就是问题所在?我会确保你从通知中得到的对象是在Root发布的同一个线程上的默认上下文中保存的。

答案 1 :(得分:3)

自从这个问题发布以来已经有一段时间了,在重新发现之后,我想为了找到这个帖子的其他人回答我自己的问题。

在我的情况下,我已经从通过NSManagedObjectContexts更新的兄弟NSManagedObjectContextDidSaveNotification迁移了大量代码库。然而,问题与此无关,即使这确实暴露了这个问题。

真正的原因是代码的旧部分,由以前的工程师设置,在NSManagedObject s上设置了KVO及其属性。据了解,核心数据实体上的KVO实际上是一个非常糟糕的主意。

更确切地说,当KVO在实体上设置并且该对象上的对象或关系的目标从NSPersistentStore中删除时,似乎发生了这种情况。第二个条件似乎不是唯一问题的原因,但在我的情况下肯定是一个非常突出的原因。

课程学到了:

  1. 在需要时使用提取的结果控制器。 KVO不是一个方便的捷径,你不应该避免将狡猾的Core Data KVO代码迁移到NSFetchedResultsControllers或其他合理的替代方案,因为拖延会伤害你。
  2. 多线程核心数据成为一名专家是一项困难但非常有价值的技能。了解您的核心数据堆栈以及核心数据多线程的细微差别绝对值得所有精神痛苦。

答案 2 :(得分:2)

一种可能性是您的持久存储已损坏且处于不一致状态。如果发生这种情况,则会生成错误代码,Magical Record不一定会处理该错误代码。这可能是与魔法记录相关的许多难以重复的明显随机崩溃的来源(可能或可能不被视为魔法记录错误)。

值得阅读魔法记录问题线程here(同一问题)和here(不同的问题,但可能是类似的原因)。当我遇到这些问题时,我设法在这些线程中的各种提示后做了一些临时补丁修复,但最终我决定删除我对Magical Record的依赖,从那时起我没有遇到任何问题。