好吧,我可以向您保证,无论是 Objective-C 的知识,还是阅读 Apple 不存在的关于子类化 NSMergePolicy 的文档,都不会帮助您解决这个问题 :)
我在我自己的小演示项目中确认,Core Data 的唯一性约束不会像人们期望的那样使用 Core Data 的级联删除规则。正如您所报告的,在您的情况下,您只是不断获得越来越多的 Address 对象。
以下代码解决了我的演示项目中重复地址对象的问题。然而,它的复杂性让人怀疑,放弃 Core Data 的唯一性约束并编写自己的老式唯一性代码是否会更好。我想这可能会表现得更糟,但你永远不知道。
在对 Address 对象进行重复数据删除时,可以将现有对象保留在持久存储中,也可以创建新对象。没关系,如果确实所有属性都相等。以下代码保留现有对象。这具有不增加对象标识符字符串表示中的“p”后缀的美观效果。它们保持为“p1”、“p2”、“p3”等。
当您创建持久化容器时,在loadPersistentStores()
完成处理程序中,您将自定义合并策略分配给托管对象上下文,如下所示:
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
container.viewContext.mergePolicy = MyMergePolicy(merge: .overwriteMergePolicyType)
...
})
最后,这是您的自定义合并策略。合并冲突中的 Client 对象传递给resolve(constraintConflicts list:)
它们的新地址对象。覆盖删除这些,然后调用 Core Data 的标准合并策略之一,该策略根据需要附加现有的 Address 对象。
class MyMergePolicy : NSMergePolicy {
override func resolve(constraintConflicts list: [NSConstraintConflict]) throws {
for conflict in list {
for object in conflict.conflictingObjects {
if let client = object as? Client {
if let addresses = client.addresses {
for object in addresses {
if let address = object as? Address {
client.managedObjectContext?.delete(address)
}
}
}
}
}
}
/* This is kind of like invoking super, except instead of super
we invoke a singleton in the CoreData framework. Weird. */
try NSOverwriteMergePolicy.resolve(constraintConflicts: list)
/* This section is for development verification only. Do not ship. */
for conflict in list {
for object in conflict.conflictingObjects {
if let client = object as? Client {
print("Final addresses in Client \(client.identifier) \(client.objectID)")
if let addresses = client.addresses {
for object in addresses {
if let address = object as? Address {
print(" Address: \(address.city ?? "nil city") \(address.objectID)")
}
}
}
}
}
}
}
}
请注意,此代码基于 Overwrite 合并策略构建。我不确定特朗普的一项政策是否更合适。
我很确定这就是你所需要的。如果我遗漏了什么,请告诉我。