我的Swift应用程序从JSON表单中的在线API下载3个数据库,然后将JSON对象转换为Coredata对象,因此该应用程序可以在Internet访问之外运行。
我有一个与类型地址实体有托有关系的实体客户端。地址与实体客户端有一个关系。
客户端< - >>地址
clients to Weldress关系的客户有一个级联删除规则,客户关系的地址具有无效的删除规则。
客户端对ID属性具有唯一性约束,并且上下文始终使用nsmergepolicytype.overwritemergepolicytype。
当实例化新客户端NSManagedObject时,保存了上下文,并且找到了具有相同ID的客户端时,新客户端覆盖了一个旧客户,一个很大的警告 - 出于某些未知的原因,旧的地址对象持续存在,现在链接到新客户。每次重新加载缓存/数据库时,都会产生每个地址的新副本。
我有多个具有这种关系和独特性的实体,这些实体正在陷入相同的结果 - 对象实例的重复。
对于诸如地址之类的对象,没有一个属性可以在容器上所有其他地址对象之间封装唯一性。它必须是所有属性(地址1,地址2,城市,州,zip等(的总和,以根据另一个地址的所有属性的总和进行检查。因此,我不确定如何通过唯一性约束来实现这一目标 - 据我所知,如果逻辑,则不能扩展独特的约束。
另一个解决方案是更改策略的合并行为或创建自定义合并策略,以确保其实际删除旧对象(级联到to-to-to-to-to-to to-to-to-to-to-to-many关系对象(,然后再将其替换为新对象对象。
我对Coredata或Objective-C还不够熟悉,无法遵循我到目前为止能够在该主题上找到的任何内容。
有人对如何进行A都有建议。
编辑:
我怀疑我对唯一性约束的假设是错误的 - 请在此处查看我的单独问题
好吧,我可以向您保证,对Objective-C的了解或阅读Apple关于子分类Nsmergepolicy的不存在的文档都不会帮助您弄清楚这一点:(
我在自己的小演示项目中确认,核心数据的独特性约束并不是人们期望的核心数据级联删除规则所期望的。如您所报告的,在您的情况下,您只会得到越来越多的地址对象。
以下代码解决了我的演示项目中重复的地址对象的问题。但是,它的复杂性使一个奇怪的是,放弃核心数据的独特性约束并编写自己的旧学校独立代码,这是否会更好。我想这可能会更糟,但是你永远不会知道。
删除地址对象时,可以将现有对象保存在持久存储中或制造新的对象。如果确实所有属性都是平等的,那应该无关紧要。以下代码保留现有对象。这具有美学上令人愉悦的效果,即不在对象标识符字符串表示中增加" P"后缀。它们仍然是" P1"," P2"," P3"等
创建持久容器时,在loadPersistentStores()
完成处理程序中,您将自定义合并策略分配给托管对象上下文:
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
container.viewContext.mergePolicy = MyMergePolicy(merge: .overwriteMergePolicyType)
...
})
最后,这是您的自定义合并策略。传递给resolve(constraintConflicts list:)
的合并冲突中的客户对象具有其新的地址对象。覆盖将删除这些,然后调用核心数据的标准合并策略之一,该策略可根据需要附加现有地址对象。
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)")
}
}
}
}
}
}
}
}
请注意,此代码基于覆盖合并策略。我不确定特朗普政策之一是否会更合适。
我很确定这就是您所需要的。让我知道我是否遗漏了任何东西。
不确定这是相关的,但是我不得不处理类似的情况。我还拥有相关的对象,这些对象似乎对它们的独特之处并没有我想要的覆盖,但是如果您考虑一下 - 它们确实具有独特的东西:这是它们与特定的独特对象有关的事实方式。因此,我这样做的方式是我对"地址"对象的足够串联数据,并为"客户端"附加了唯一键,这是我的"地址"的唯一键。