使用 CoreData 和 CloudKit 同步关系
Syncing relationships using CoreData and CloudKit
TLDR 版本: 我的应用如何知道设备 A 上的 CoreData 对象、设备 B 上的 CoreData 对象和 CloudKit [=41= 中的 CKRecord ]都是同一条记录?
详细版本:
我正在开发一个在本地使用 CoreData 并 CloudKit 在设备之间同步的应用程序。我不明白在添加多个设备后,CoreData 关系和 CloudKit 引用应该如何协同工作。
我理解的一些道理:
1) 当您创建一个 CoreData 对象时,它会被分配一个 objectID。您不能自己在创建时分配一个或修改一个已经存在的。从 CoreData 关系字段中,您可以直接访问相关对象,也可以使用便捷方法获取这些相关对象的 objectID。
2) 当你创建一个CloudKit 记录时,你可以给它分配一个recordName(基本上相当于CloudKit CoreData objectID)或者默认生成一个。 CloudKit 引用字段包含一个字符串,它是关联记录的 recordName。
所以这是我的应用程序的工作方式(和不工作)
设备A第一次启动。 CoreData 实例化了一堆默认对象,用户可以在使用应用程序时编辑(或添加 to/delete)。当设置完成并且应用程序确定一切正常时,它会与 CloudKit 同步。它首先查看已存在的任何记录 (none),然后使用 CoreData 对象 ID 作为 CloudKit 记录名称将新记录上传到 CloudKit。因此设备 A 上的对象 ID 和 CloudKit 记录名称是相同的。这些不同的对象之间存在多种关系。到目前为止一切顺利 - 这部分有效(仪表板中的修改正确更新核心数据中的关系,反之亦然)。
当设备 B 首次启动时,rails 一切都结束了。 CoreData 实例化相同的一组默认对象(具有唯一的 objectID),然后用户可以在使用该应用程序时修改或 add/delete。当设置完成并且一切顺利时,它会与 CloudKit 同步。它从 CloudKit 中提取所有现有记录并更新匹配的本地记录。匹配 永远不会发生 基于 recordName <-> objectID,因为设备 B 具有唯一的 objectID。这是我理解不足的地方。
我目前尝试的解决方案
我目前的解决方案是向 CoreData 实体和 CloudKit 记录添加自定义 ckID 字段。在每个设备上的第一次同步时,它 尝试 适当地同步这些字段。如果 CloudKit 中有记录,它会遍历这些记录并尝试根据自定义字段和实体类型将现有的 CoreData 对象与那些 CloudKit 记录相匹配——例如 'name' 字段实体。当它找到匹配项时,它会在本地更新 ckID 字段。如果找到 none,它会创建一个新的 CoreData 对象。每当应用程序查找 CoreData 关系或创建 CKReference 时,都会使用此 ckID 字段。总的来说,感觉我做了很多本不该做的工作。
提前感谢您的帮助!
2017 年 11 月 3 日更新
一周后,总的来说,这肯定是错误的设备间同步方式。我的自定义 ID 字段不同步导致各种混乱。
我仍然相信我在这里遗漏了一些非常基本的东西。记录如何与位于不同位置的自身相关?如果可以修改现有的 CoreData objectID(或在创建时分配一个),这将很容易——我错过了什么?!?我现在所做的感觉很不对,但我正在努力前进,不知道还能尝试什么...
TLDR 版本: 我的应用如何知道设备 A 上的 CoreData 对象、设备 B 上的 CoreData 对象和 CloudKit [=41= 中的 CKRecord ]都是同一条记录?
详细版本:
我正在开发一个在本地使用 CoreData 并 CloudKit 在设备之间同步的应用程序。我不明白在添加多个设备后,CoreData 关系和 CloudKit 引用应该如何协同工作。
我理解的一些道理:
1) 当您创建一个 CoreData 对象时,它会被分配一个 objectID。您不能自己在创建时分配一个或修改一个已经存在的。从 CoreData 关系字段中,您可以直接访问相关对象,也可以使用便捷方法获取这些相关对象的 objectID。
2) 当你创建一个CloudKit 记录时,你可以给它分配一个recordName(基本上相当于CloudKit CoreData objectID)或者默认生成一个。 CloudKit 引用字段包含一个字符串,它是关联记录的 recordName。
所以这是我的应用程序的工作方式(和不工作)
设备A第一次启动。 CoreData 实例化了一堆默认对象,用户可以在使用应用程序时编辑(或添加 to/delete)。当设置完成并且应用程序确定一切正常时,它会与 CloudKit 同步。它首先查看已存在的任何记录 (none),然后使用 CoreData 对象 ID 作为 CloudKit 记录名称将新记录上传到 CloudKit。因此设备 A 上的对象 ID 和 CloudKit 记录名称是相同的。这些不同的对象之间存在多种关系。到目前为止一切顺利 - 这部分有效(仪表板中的修改正确更新核心数据中的关系,反之亦然)。
当设备 B 首次启动时,rails 一切都结束了。 CoreData 实例化相同的一组默认对象(具有唯一的 objectID),然后用户可以在使用该应用程序时修改或 add/delete。当设置完成并且一切顺利时,它会与 CloudKit 同步。它从 CloudKit 中提取所有现有记录并更新匹配的本地记录。匹配 永远不会发生 基于 recordName <-> objectID,因为设备 B 具有唯一的 objectID。这是我理解不足的地方。
我目前尝试的解决方案
我目前的解决方案是向 CoreData 实体和 CloudKit 记录添加自定义 ckID 字段。在每个设备上的第一次同步时,它 尝试 适当地同步这些字段。如果 CloudKit 中有记录,它会遍历这些记录并尝试根据自定义字段和实体类型将现有的 CoreData 对象与那些 CloudKit 记录相匹配——例如 'name' 字段实体。当它找到匹配项时,它会在本地更新 ckID 字段。如果找到 none,它会创建一个新的 CoreData 对象。每当应用程序查找 CoreData 关系或创建 CKReference 时,都会使用此 ckID 字段。总的来说,感觉我做了很多本不该做的工作。
提前感谢您的帮助!
2017 年 11 月 3 日更新
一周后,总的来说,这肯定是错误的设备间同步方式。我的自定义 ID 字段不同步导致各种混乱。
我仍然相信我在这里遗漏了一些非常基本的东西。记录如何与位于不同位置的自身相关?如果可以修改现有的 CoreData objectID(或在创建时分配一个),这将很容易——我错过了什么?!?我现在所做的感觉很不对,但我正在努力前进,不知道还能尝试什么...