SwiftData 教程与示例:添加 CloudKit 云同步(六)
了解如何为你的 iOS 应用添加 CloudKit 集成,并使用 iCloud 自动云同步你的应用数据。
如果你已经使用 SwiftData 完成了持久化数据,你就可以使用 iCloud 轻松地将你的应用数据备份到云端,防止在用户卸载应用之后丢失本地数据。
你还可以使用 iCloud 将这些数据同步到多部设备上。
为项目添加 iCloudKit 服务
在 Xcode 中,导航到 signing & Capabilities 中,点击左上角的 + Capability:
在打开页面中找到 iCloud 并添加它。在 Services 中,勾选 CloudKit 选项:
为 CloudKit 服务创建容器
添加 CloudKit 服务后,要使用 CloudKit 服务,必须添加 Container:
Container 是一个存储区域,用来保存和管理你的应用在 iCloud 上的所有数据。每个 Container 就像是一个数据库,可以在不同设备之间同步用户数据或让多个用户共享数据。
每个 CloudKit Container 都需要一个唯一的标识符(名称),推荐设置为与你 App 的 Bundle Identifier 一致即可,Xcode 会自动为其添加 iCloud.
前缀:
为项目添加 Remote notifications 服务
CloudKit 使用 Remote Notifications (推送通知服务)来保持设备间的数据同步。要使用 CloudKit 的 Remote Notifications ,必须在项目 Info.plist 中启用 remote-notification 后台模式。
和添加 CloudKit 方法类似,在 + Capability 中搜索「Background Modes」并添加,然后在 background Modes 中勾选「Remote notifications」:
完成 CloudKit 服务集成
完成上述配置之后,你已经完成了所有的配置工作,没错,就是这么简单。
但是由于 CloudKit 对 SwiftData 数据模型有非常严格的规范要求,你之前定义的数据模型在设备本地存储可能没有问题,但在启用 CloudKit 之后可能会遇到崩溃、卡死的问题。
你可以参考下面【常见错误与解决方案】部分来调整你的代码。
如果你已经修复了所有报错,在成功运行 App 之后,会在 Xcode 中看到大量与 CloudKit 相关的 DEBUG 信息输出:
这些日志是 SwiftData 与 CloudKit 集成的正常调试输出,显示了数据同步、CloudKit 配置、自动导入/导出等过程。如果您看到了这些输出,说明应用的 iCloud/CloudKit 同步功能正在正常工作。
CloudKit 后续工作
禁用 CloudKit 调试日志
为应用集成 CloudKit 服务之后,每次运行 App 时,默认 CloudKit 会将所有事件记录到控制台,这会严重妨碍其他调试信息:
通过在 Xcode 启动项中,添加以下两行记录,可以减少输出:
- 禁用 CoreData 调试输出
-com.apple.CoreData.Logging.stderr 0
- 禁用 CloudKit 调试输出
-com.apple.CoreData.CloudKitDebug 0
获取 CloudKit 数据同步状态
- 如何检测带有 CloudKit 的 SwiftData 是否已完成从其他地方同步新数据?
- 如何检测是否还有更改需要同步?
- 如何获取何时进行了 CloudKit 数据同步?
由于 SwiftData 是新的框架,截止 2024 年 10 月,Apple 尚未提供相关的接口用于获取以上数据。
常见错误与解决方案
缺少逆向关系(all relationships have an inverse)
运行 App 出现以下错误提示:
CloudKit integration requires that all relationships have an inverse, the following do not:
这是因为 CloudKit 要求 SwiftData 模型中的所有关系都有逆向关系。这对于维护数据的一致性和设备间的同步是必要的。
可以参考提示找到是哪些 @Relationship
尚未设置 inverse
参数,并添加上即可。
可以参考这篇文章中对于「逆向关系」的详细讲解:
缺少默认值的非可选属性(all attributes be optional)
运行 App 出现以下错误提示:
CloudKit integration requires that all attributes be optional, or have a default value set. The following attributes are marked non-optional but do not have a default value:
CloudKit 要求 SwiftData 中所有数据模型的数据必须设置为可选或者设置默认值。
非可选的关系(all relationships be optional)
运行 App 出现以下错误提示:
CloudKit integration requires that all relationships be optional, the following are not:
CloudKit 要求所有关系都是可选的,以防止在同步时缺少相关对象导致的问题。
可以参考我这篇文章中,关于【设置关系属性为可选】部分的讲解:
不支持的唯一约束(not support unique constraints)
运行 App 出现以下错误提示:
CloudKit integration does not support unique constraints. The following entities are constrained:
CloudKit 不支持在 SwiftData 模型中定义的唯一约束。唯一约束可能会在数据同步时导致冲突。
可以参考我这篇文章中,关于【避免使用唯一约束】部分的讲解: