ios - 使用 CoreData 和 CloudKit 同步关系

标签 ios core-data cloudkit

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 只是一个传输层,实现同步本身就是一个野兽。

我建议查看现有的解决方案,例如 Ensembles , Seam ,或SyncKit (我是作者)

关于ios - 使用 CoreData 和 CloudKit 同步关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46965649/

相关文章:

ios - CloudKit 应用程序可处理不同的 iCloud 帐户

objective-c - 在 UIViewController 中加载和卸载数据

ios - 本地图 View 只是屏幕的一部分时,如何在 iOS 模拟器中缩小?

cocoa - 刷新获取的NSManagedObject属性

swift - 无法将类型 CKAsset 的值分配给类型 UIImage

swift - Realm 对象服务器 - 错误 : Your request parameters did not validate

ios - 为什么之前调用 reloadRows 时 UITableView setContentOffset 无法正常工作?

javascript - 在 iOS 应用程序中嵌入 JavaScript 引擎

iphone - 显示按日期对核心数据进行排序

core-data - Swift - 在应用程序组中共享核心数据模型(带扩展)