从 CoreData 关系中获取错误实体的对象

Posted

技术标签:

【中文标题】从 CoreData 关系中获取错误实体的对象【英文标题】:Objects of wrong entity fetched from CoreData relationship 【发布时间】:2016-10-11 16:30:55 【问题描述】:

我有一个相当大的 CoreData 模型,它突然表现得很奇怪。共有三个相关实体:

用户 故事 组

User 有一个名为 storiesStory 对象的多对多关系和一个多对多关系 groupsGroup 对象。两者也都有适当的逆。我使用 mogenerator 为所有属性和关系生成便利访问器。两者都是有序对多关系。

现在有时会发生,当我向用户对象询问其groups(如user.groups)时,我实际上得到了一组 NSOrdered 的 XNGStory 对象。在我观察到的少数情况下,它们与user.stories 返回的对象相同。这两个集合不一样(不同的指针),但它们的内容是(我通过在它们上调用array] valueForKeyPath:@"objectID.URIRepresentation"] 进行检查,并在两种情况下以相同的顺序获得相同的 URI)。

感觉好像我的应用程序中有某种方式将故事存储在 groups 关系中,但我检查了代码,只有与组相关的类触及 groups 关系,只有故事相关的类触及 @987654334 @-关系。两者之间也没有交互或关系,它们在应用程序的完全独立的部分中使用,所以我不知道这种数据损坏是如何发生的。

是否有任何原因可能会发生这种数据损坏?当我意外地将对象存储在错误的关系中时,我本来希望 CoreData 会抱怨。

还有一件事:到目前为止,我们只能在 ios 10 上重现它。

我们尝试过的事情:

我们首先怀疑存在内存问题(因为错误类型的对象出现在不应该出现的位置),但在启用 Address Sanitizer 和 NSZombies 的情况下运行并没有发现任何问题。此外,一旦出现问题,它会在应用重新启动时持续存在,并且使用调试器在对象中四处寻找也显示出一致(错误)的数据模型,因此错误的不仅仅是一个指针。 已停用 WAL(问题仍然存在) 在与Core Data Editor 发生崩溃后查看 sqlite 文件(包括和不包括 WAL):它显示 groups 关系的组对象,所以在 sqlite 数据库级别上似乎一切都很好 -> 不知何故从文件加载时,关系会混淆。

【问题讨论】:

【参考方案1】:

据我所知,这似乎是 iOS 10 的错误。

我们在使用 Core Data 的应用程序中遇到了类似的问题 - User 对象具有 Addresses(与 Address 对象)和 Friends(与其他 User 对象)的关系。

由于某些原因在iOS 10 Core Data下偶尔会选择返回Friends关系中的Address对象。

我们已经对 iOS 9 进行了回归测试,并且没有出现此问题。

Open Radar 上存在一个针对同一问题的开放错误 - 26826183。有趣的是,我们只是在 10.0.2 下才开始看到此问题,但 Radar 报告基于早期的 iO​​S 10 Beta。

【讨论】:

我收到来自应用程序用户的报告,称 Core Data 存在错误并且无法获取数据。两个用户都安装了 10.0.2。【参考方案2】:

我们对此进行了广泛的测试,并得出结论认为这是一个 iOS 10 错误。它似乎也与我们的任何代码无关,仅与数据模型有关。我们能够使用我们的数据模型、Xcode 8 的代码生成和 iOS 10 的新 NSPersistentContainer(在它破坏之前使用 mogenerator 和“设置 CoreData 堆栈的旧方法”)在示例项目中重新创建问题。

要重现该问题,我们执行以下操作:

    在启动时,如果没有User-object,则创建一个User-object并添加10个Group对象并保存。 然后添加一个Story 到它,仍然在主上下文中,然后保存。 终止应用(通过 iOS 向上滑动或简单地通过在 Xcode 中按“停止”) 再次启动应用程序。启动时,获取User 对象,将Story 对象添加到stories 关系并保存。 检查背景或主上下文中的user.groups 关系。它现在包含 XNGStory 对象,尽管它应该仍然有 XNGGroup 对象。

我在示例项目中提交了一份 Radar。 OpenRadar 是here(没有示例项目,因为它包含我们的数据模型)。​​

问题似乎高度依赖于数据模型设置。当我们的 User 实体上的 all-but-on 关系被排序时,就会发生这种情况。如果所有都是有序的,它就不会发生,如果两个或更多是无序的,它也不会发生。

【讨论】:

以上是关于从 CoreData 关系中获取错误实体的对象的主要内容,如果未能解决你的问题,请参考以下文章

CoreData:错误 - 实体不是键值编码兼容的 ID

核心数据 - 在不触发错误的情况下获取对多关系的 objectID

在 coredata 中获取关系对象

如何使用CoreData获取相关实体的对象?

在一对多 CoreData 关系错误上调用“计数”是不是会将集合中的所有对象都带入内存?

CoreData 困境:没有反向关系的实体