核心数据唯一约束 - "悬挂对无效对象的引用"在保存

时间:2016-04-15 14:22:18

标签: ios cocoa-touch core-data

我在新模型版本中为现有应用引入了唯一约束。

模型具有实体Person,其与实体Pet具有可选的一对一关系。人的删除规则是级联的,而Pet的反向关系删除规则是无效的。还有另一个实体,Job,Person也有一对一的关系。但是,删除规则和反向删除规则都是无效的。

人有一个" personID"我独特的财产。

在主队列上下文中,我有一个ID为xxx的Person实例,没有Pet set。让我们称呼那个人"查理"。我也创建了一个Job,并将其设置为" iOS Dev",并将其分配给Charlie的工作属性。

然后在子私有队列上下文中,我插入一个新的" Charlie"还有ID xxx(唯一约束)并创建一个Pet并设置它。我没有设置工作。我保存了子上下文没有问题。

之后,我尝试保存主队列上下文。但就在此之前,我检查主队列上下文的insertedObjects属性,并按照我的预期看到ID为xxx的Person实例。我期待的是,这个第二个实例将由唯一约束处理并且被"合并"与前一段中的原始Person实例一起使用。但是,当我实际调用MOC的save:方法时,它抛出异常并检查NSError对象:

  

错误域= NSCocoaErrorDomain代码= 1550"操作不可能   完成。 (可可错误1550。)" UserInfo = {悬挂引用   无效的对象。= null

有关如何避免异常的任何想法?我曾经习惯于"悬挂参考文献"在核心数据中意味着关系配置错误,但我已经多次重复它并且它看起来很好,所以我不确定还有什么可以排除故障。我使用NSMergeByPropertyObjectTrumpMergePolicy合并策略涉及所有上下文。

显然这有点难以理解,所以我在Github上提出了一个示例项目以防任何人感兴趣:https://github.com/bpapa/core-data-unique-bug

3 个答案:

答案 0 :(得分:4)

我在这上面烧了代码级支持票,Apple工程师确认存在错误。作为一种解决方法,建议编写我自己的调用super的合并策略,然后手动确保两端都设置了关系。

答案 1 :(得分:1)

如果您想采用新的iOS 9 Unique Constrains策略,则必须确保两个上下文都设置了相同的合并策略

请注意,如果您的对象的较新实例具有nil的属性/关系且您的意图始终是“扩充”,则会帮助您对象,即填充任何缺少的属性并更新现有属性。

否则,对于iOS9之前的版本,以下内容有效。

或许对您使用的合并政策的含义存在一些误解(NSMergeByPropertyObjectTrumpMergePolicy)。它指的是在内存中有一个对象版本而在持久性存储中有另一个版本的情况,而不是在不同上下文中的内存中有两个版本。从头文件:

  

此单例策略合并持久性商店的对象版本与当前内存版本之间的冲突。

因此,您创建对象的过程不是正确的方法。

相反,您应该使用唯一ID在子上下文中获取Person

或者,您可以使用{i}个(不透明的Core Data工件)可供子上下文使用objectID获取对象图中同一对象的引用。

答案 2 :(得分:0)

使用背景上下文中的did save通知将更改合并到主上下文中。参见苹果地震样本。