使用 CoreData 和 CloudKit 同步关系

Bri*_*n M 5 core-data ios cloudkit

TLDR 版本:我的应用程序如何知道设备 A 上的 CoreData 对象、设备 B 上的 CoreData 对象和 CloudKit 中的 CKRecord都是相同的记录

详细版本:

我正在开发一个在本地使用 CoreData 和 CloudKit 在设备之间同步的应用程序。一旦添加了多个设备,我不明白 CoreData 关系和 CloudKit 引用应该如何协同工作。

我所理解的一些真理:

1) 当您创建 CoreData 对象时,它会被分配一个 objectID。您不能在创建时自己分配一个或修改已经存在的一个。从 CoreData 关系字段中,您可以直接访问相关对象,也可以使用方便的方法获取这些相关对象的 objectID。

2)当你创建一个 CloudKit 记录时,你可以给它分配一个 recordName(基本上是一个 CoreData objectID 的 CloudKit 等价物)或者一个默认生成的。CloudKit 引用字段包含一个字符串,它是关联记录的 recordName。

所以这是我的应用程序的工作方式(并且不起作用)

设备 A 首次启动。CoreData 实例化了一堆默认对象,然后用户可以在使用应用程序时对其进行编辑(或添加/删除)。当设置完成并且应用程序确定一切正常时,它会与 CloudKit 同步。它首先查找已存在的所有记录(无),然后使用 CoreData objectID 作为 CloudKit 记录名称将新记录上传到 CloudKit。所以设备 A 上的对象 ID 和 CloudKit 记录名称是相同的。这些不同的对象之间存在多种关系。到目前为止一切顺利 - 这部分工作(仪表板中的修改正确更新核心数据中的关系,反之亦然)。

当设备 B 首次启动时,事情现在就出轨了。CoreData 实例化相同的一组默认对象(具有唯一的 objectID),然后用户可以在使用应用程序时修改或添加/删除这些对象。当设置完成并且一切顺利时,它会与 CloudKit 同步。它从 CloudKit 中提取所有现有记录并更新匹配的本地记录。永远不会根据 recordName <-> objectID 进行匹配,因为设备 B 具有唯一的 objectID。这是我的理解不足的地方。

我目前尝试的解决方案

我目前的解决方案是向 CoreData 实体和 CloudKit 记录添加自定义 ckID 字段。在每个设备上的第一次同步时,它会尝试适当地同步这些字段。如果 CloudKit 中有记录,它会通过这些记录并尝试根据自定义字段和实体类型将现有的 CoreData 对象与这些 CloudKit 记录匹配 - 例如实体的“名称”字段。当它找到匹配项时,它会在本地更新 ckID 字段。如果没有找到,它会创建一个新的 CoreData 对象。每当应用程序查找 CoreData 关系或创建 CKReference 时,都会使用此 ckID 字段。总的来说,这感觉就像我正在做很多我不应该做的工作。

预先感谢您的任何帮助!

更新 11/3/17

一周后,总的来说,这似乎是在设备之间进行同步的错误方式。我的自定义 ID 字段不同步导致各种混乱。

我仍然相信我在这里遗漏了一些非常基本的东西。记录如何与不同位置的自身相关?如果可以修改现有的 CoreData objectID(或在创建时分配一个),这将很容易 - 我错过了什么?!?我现在正在做的事情感觉很不对,但我正在努力前进,不知道还能尝试什么......

小智 4

正如您所提到的,设备 A 和设备 B 上的 objectID 会有所不同。如果您确实想避免对象中的标识符字段,您可以在每个设备上进行查找以从 recordName 映射到 objectID,但是如果您更新了核心数据模型你的objectID会改变,所以这种方法会非常不灵活。

您使用 ckID 字段的方法是正确的,是的,您实际上需要做这么多工作。CloudKit 只是一个传输层,实现同步本身就是一个野兽。

我建议查看现有的解决方案,例如EnsemblesSeamSyncKit(我是其中的作者)