LESSON 46 / 576 分钟

离线、冲突与删除:同步真正困难的地方

两台设备都能离线修改,就可能出现互不知情的新版本。同步需要处理这些历史,而不仅是复制最新 UI。

用你的前端经验理解

可以借用 Git 的版本、共同祖先和合并思路;数据库记录不一定能按文本行合并,“最后写入获胜”也可能覆盖有价值的信息。

为什么需要它

同步最难的不是传输,而是多个副本各自合法修改后如何形成可解释结果。离线时设备没有完整全局信息,更新时间还可能受设备时钟影响。你需要按数据语义定义规则:标题需要保留用户意图,计数可能需要操作记录,删除则必须防止旧副本再次上传导致复活。

它是怎样工作的

可以把同步想成带身份的变更日志:每次变更有记录 ID、操作 ID 和版本依据,服务端或同步层检查是否基于旧版本。重复投递由幂等处理消化,冲突则选择字段合并、冲突副本或明确决胜规则。tombstone 保留删除事实,但何时安全清理取决于副本与同步协议,不是随意保留几秒。

把关键概念连起来

1

先区分状态

本地已保存、待上传、拉取中、冲突、失败与云不可用属于不同情况。重试要避免重复写入,可借助稳定操作/记录 ID 与可持久化的待处理状态。

2

冲突策略

显式 CloudKit 写入可根据服务端版本变化处理冲突;按字段合并、保留双方副本、用户选择都可能合理。SwiftData 自动镜像与自建 CKSyncEngine 的控制能力不同。

3

删除与恢复

离线设备可能再次带回旧内容。设计同步引擎时要处理删除变更/墓碑、变更令牌和账户切换;不能只拉当前记录而忽略删除历史。失败按错误类型退避重试。

“周末读”变成了两个标题

手机离线改成“周末读 Swift”,Mac 离线改成“周末读设计”。如果直接覆盖,就丢失一个意图;可以保留双方副本或让用户选择。框架具体怎样检测/合并,需要用真实工程验证。

推演删除与离线编辑相遇

  1. A 删除文章,B 离线修改同一文章标题。B 上线时不能简单把自己的整条记录当作新建上传。
  2. 合并层识别相同记录身份与删除事实,按产品规则保持删除,或明确提示恢复冲突内容。
  3. 相同变更重试多次后,最终结果仍应稳定,不能有时删除、有时重新出现。

这里需要你亲自判断

实验里的“手动选择版本”是帮助理解的冲突策略,不代表 SwiftData 默认会弹出冲突窗口,也不代表 CloudKit 自动采用相同规则。

做一个小练习

在同步实验中分别离线修改手机和 Mac 标题,再尝试同步并选择保留版本;解释覆盖与保留双方的代价。

  1. 在同步实验中制造双方改标题,再测试一方删除另一方编辑。
  2. 为“已读状态能否从 true 改回 false”定义规则,避免用逻辑 OR 意外禁止取消已读。
展开参考思路与验收标准

正确策略取决于业务意图。并非所有布尔值都可简单 OR,也并非最后时间戳就代表最后用户意图;规则应该能用一组固定冲突案例验证。

打开对应交互实验

两台设备基于同一旧版本各改标题,应该首先认识到什么?

继续查阅官方资料
Apple Developer 官方资料

本课聚焦核心认知。具体 API、系统要求与发布政策,以当前官方文档和工程验证为准。

答对理解题后即可标记完成