跨应用数据共享方案选型:NSPersistentCloudKitContainer、App Groups或二者联用?
Core Data 多应用共享方案选型与冲突规避解答
方案选型:单一方案还是组合方案?
优先选择App Groups + NSPersistentCloudKitContainer的组合方案,二者不存在功能冗余,职责完全互补:
- App Groups负责同设备下多应用的本地数据共享,把SQLite存储放在共享组目录后,同设备所有授权应用都可以直接读写同一份存储文件,数据变更无延迟
- NSPersistentCloudKitContainer只负责跨设备的iCloud同步逻辑,解决多设备间的数据一致性问题
- 单独使用NSPersistentCloudKitContainer无法解决同设备同步延迟、同步状态不可感知的问题;单独使用App Groups则完全不具备跨设备同步能力,二者组合是目前兼顾同设备实时性、跨设备同步能力的最优解。
同设备多应用同时访问共享SQLite是否会冲突?
默认未做适配的情况下一定会出现冲突,正确配置后可以稳定支持多进程同时访问:
Core Data的SQLite存储原生支持多进程访问,但所有接入共享存储的应用必须完成以下配置,否则会出现数据不一致、甚至存储文件损坏的问题:
- 所有应用的持久化存储协调者都需要注册
NSPersistentStoreRemoteChange通知,监听其他进程的写入操作 - 收到跨进程写入通知后,及时刷新托管对象上下文的缓存,可调用
context.refreshAllObjects()清理旧缓存,避免基于过期数据执行写入 - 所有写入操作尽量使用短事务,不要长时间持有数据库写锁,避免其他进程写入排队超时。
已实现App Groups同设备共享是否需要接入CloudKit?
完全取决于产品需求,没有强制要求:
- 如果系列应用只需要支持单设备内的数据共享,用户没有多设备(iPhone、iPad、Mac等登录同一Apple ID的设备)同步数据的需求,不需要接入CloudKit——App Groups的本地共享读写性能、实时性远高于CloudKit同步
- 如果需要支持跨设备的数据同步能力,就必须接入CloudKit。App Groups是设备本地的沙盒共享机制,本身不具备任何跨设备传输数据的能力。
单独使用NSPersistentCloudKitContainer的冲突规避方案
单独使用NSPersistentCloudKitContainer时,每个应用都会在本地沙盒维护独立的Core Data副本,靠CloudKit做双向同步,这种架构天然存在最终一致性延迟,无法做到100%零冲突,只能通过以下规则最大程度降低冲突概率,尤其是应用前后台切换场景的异常:
- 应用触发进入后台的生命周期回调时,第一时间执行
viewContext.save()把所有内存中的未保存变更写入本地存储,同时触发CloudKit的同步上传,不要把未提交的变更留在内存中 - 应用即将进入前台时,主动触发CloudKit的同步拉取,通过监听
NSPersistentCloudKitContainer.eventChangedNotification跟踪同步事件状态,待拉取同步完成后再刷新UI加载最新数据,避免用户看到旧数据 - 全局统一配置托管对象上下文的合并策略为
NSMergeByPropertyObjectTrumpMergePolicy,以最新的属性值为准做自动合并,避免合并冲突直接导致应用崩溃 - 如果已经接入App Groups共享存储,直接将NSPersistentCloudKitContainer的本地存储路径指向App Groups共享目录下的SQLite文件,让同设备所有应用共用同一份本地存储,从根源上消除同设备多副本同步带来的冗余和冲突问题。
内容的提问来源于stack exchange,提问作者Toby Evetts
相关产品推荐
相关产品推荐

