TLDR 版本:我的应用如何知道设备 A 上的 CoreData 对象、设备 B 上的 CoreData 对象和 CloudKit 中的 CKRecord 都是相同的记录?
详细版本:
我正在开发一个在本地使用 CoreData 和 CloudKit 在设备之间同步的应用程序。我不明白一旦添加多个设备,CoreData 关系和 CloudKit 引用应该如何协同工作。
我所理解的一些事实:
1) 当您创建 CoreData 对象时,它会被分配一个 objectID。您不能在创建时自行分配一个或修改已经存在的一个。从 CoreData 关系字段中,您可以直接访问相关对象,也可以使用便捷的方法获取这些相关对象的 objectID。
2) 创建 CloudKit 记录时,可以为其分配一个 recordName(基本上相当于 CoreData objectID 的 CloudKit),或者默认生成一个 recordName。 CloudKit 引用字段包含一个字符串,该字符串是关联记录的 recordName。
这就是我的应用程序的工作方式(和不工作方式)
设备 A 首次启动。 CoreData 实例化一堆默认对象,用户可以在使用应用程序时对其进行编辑(或添加/删除)。当设置完成并且应用程序确定一切正常时,它会与 CloudKit 同步。它首先查找已存在的所有记录(无),然后使用 CoreData objectID 作为 CloudKit recordNames 将新记录上传到 CloudKit。因此设备 A 上的 objectID 和 CloudKit recordName 是相同的。这些不同的对象之间存在多种关系。到目前为止一切顺利 - 这部分有效(仪表板中的修改正确更新了 coredata 中的关系,反之亦然)。
随着设备 B 首次启动,事情开始偏离轨道。 CoreData 实例化同一组默认对象(具有唯一的 objectID),用户可以在使用应用程序时对其进行修改或添加/删除。当设置完成且一切正常后,它会与 CloudKit 进行同步。它从 CloudKit 中提取所有现有记录并更新匹配的本地记录。基于 recordName <-> objectID 的匹配永远不会发生,因为设备 B 具有唯一的 objectID。这是我的理解不足的地方。
我当前尝试的解决方案
我目前的解决方案是将自定义 ckID 字段添加到 CoreData 实体和 CloudKit 记录中。在每个设备上第一次同步时,它会尝试适本地同步这些字段。如果 CloudKit 中有记录,它会遍历这些记录,并尝试根据自定义字段和实体类型(例如实体的“名称”字段)将现有 CoreData 对象与这些 CloudKit 记录进行匹配。当它找到匹配时,它会在本地更新 ckID 字段。如果没有找到,它会创建一个新的 CoreData 对象。每当应用程序查找 CoreData 关系或创建 CKReference 时,都会使用此 ckID 字段。总的来说,我感觉我做了很多本不应该做的工作。
预先感谢您的帮助!
2017 年 11 月 3 日更新
一周后,总的来说,这似乎是设备之间同步的错误方式。我的自定义 ID 字段不同步,导致各种困惑。
我仍然相信我在这里遗漏了一些非常基本的东西。不同位置的记录如何与其自身相关?如果可以修改现有的 CoreData objectID(或在创建时分配一个),这将很容易 - 我错过了什么?!?我现在所做的事情感觉非常错误,但我正在努力前进,不知道还能尝试什么......
最佳答案
正如您所提到的,设备 A 和设备 B 上的 objectID 会有所不同。 如果您确实想避免对象中出现标识符字段,您可以在每个设备上进行查找以从 recordName 映射到 objectID,但是如果您更新了核心数据模型您的 objectID 将发生变化,所以这方法将非常不灵活。
您使用 ckID 字段的方法是正确的,是的,您实际上需要做这么多工作。 CloudKit 只是一个传输层,实现同步本身就是一个野兽。
关于ios - 使用 CoreData 和 CloudKit 同步关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46965649/