核心摘要:启用 CloudKit 同步很简单,但让它稳定运行很难。绝大多数对模型调整后的同步错误都源于违反了数据模型的硬性物理限制。请务必在设计阶段遵守以下规则。
在为 Core Data 或 SwiftData 启用 CloudKit 同步时,由于 CloudKit 本身的分布式特性,它对本地数据模型(Schema)有着比纯本地数据库更严格的要求。如果未在建模阶段充分考虑这些限制,后期调整将异常痛苦。
数据模型必须遵守的硬性规则
以下规则是强制性的,违反任何一条都会导致同步失败或应用崩溃。
1. 禁止唯一性约束 (No Unique Constraints)
CloudKit 不支持原子性的唯一性检查。
- Core Data: 禁止在 Entity 的 Configuration 中配置
Unique constraints。 - SwiftData: 禁止在属性上使用
@Attribute(.unique)宏。
2. 属性必须可选或有默认值
CloudKit 需要能够处理“部分数据”同步的情况。
- 禁止:非可选(Non-Optional)且没有默认值的属性。
- 允许:
- 可选类型(Optional,
?) - 非可选但设有默认值(Default Value)
- 可选且有默认值
- 可选类型(Optional,
3. 类型限制
- 禁止:使用 Core Data 的
Undefined类型。
4. 关系 (Relationships) 的严格要求
这是最容易出错的地方:
- 必须可选:所有 Relationship 必须设置为
Optional。 - 必须有逆向:所有 Relationship 必须设置
Inverse(逆向关系)。在一些情况下,SwiftData 宏会自动处理,但在 Core Data编辑器中需手动指定。 - 禁止 Deny 删除规则:Delete Rule 不能设为
Deny。 - 禁止有序关系:Core Data 中不能勾选
Ordered(Arrangement)。SwiftData 没有该选项。
迁移策略:只增不减
启用 CloudKit 后,Schema 的变更受到极大限制。你只能使用轻量迁移(Lightweight Migration)。
严格的修改限制
一旦应用上线(Schema 推送到 Production 环境),请遵守 “只增、不减、不改” 原则:
- 禁止删除:不要删除已存在的 Entity 或 Attribute。即使你不再使用,也请保留在模型中。
- 禁止重命名:不要重命名 Entity 或 Attribute。CloudKit 会将其视为“删除了旧的,添加了新的”,导致旧数据丢失且同步异常。
- 禁止修改类型:不要改变属性的数据类型(如从 String 改为 Int)。
推荐做法
如果必须修改模型:
- 添加新属性:这是最安全的做法。
- 废弃旧属性:在代码层面不再使用旧属性,但保留模型定义。