NSPersistentCloudKitContainer
我有一个用于与 iCloud 同步数据的应用程序。用户报告偶尔会丢失数据,之后我开始调试我的实现。
我的应用程序实现的一部分是显示一个显示信息并有一个确认按钮的弹出窗口。当用户单击此按钮时,自定义子类的一个或多个实例NSManagedObject
被修改。
同时,NSPersistentCloudKitContainer
当应用退出并变为活动状态时,会触发一个镜像进程。当用户单击上述确认按钮时会发生这种情况。它通过执行NSCloudKitMirroringExportRequest
andNSCloudKitMirroringImportRequest
请求来做到这一点。
换句话说,在我的应用程序中,数据同时被修改(通过代码显式)和镜像(通过 CloudKit 隐式),这就是问题所在。
本质上是这样的:
NSTimeInterval
子类实例的属性 ( )NSManagedObject
递增(例如 0 + 1 = 1)。NSPersistentCloudKitContainer
当应用程序激活或退出时隐式开始镜像数据。- 在此过程中但在完成之前,该属性会再次递增(例如 1 + 1 = 2)。
- 在内部,镜像过程完成。
在这个阶段,我希望属性的值与最新的(本地)更改相匹配(因此在我的示例 2 中)。但相反,它匹配初始增量(因此在我的示例 1 中),覆盖我的最新(本地)更改导致数据丢失。显然,NSCloudKitMirroringImportRequest
恢复到镜像进程启动时的状态,也可以在日志中看到:
CoreData: debug: CoreData+CloudKit: -[PFCloudKitImporterZoneChangedWorkItem applyAccumulatedChanges:error:]
[…]
Importing updated records:
(
"<CKRecord: 0x10225b560; recordID=5458F9C8-7BE2-4563-92DE-650ED4C643F5:(com.apple.coredata.cloudkit.zone:__defaultOwner__), recordChangeTag=23, values={\n \"CD_activity\" = \"3E497A4C-6467-48F4-B7F4-6F1B2B7BC779\";\n \"CD_date\" = \"2020-04-26 07:28:00 +0000\";\n \"CD_duration\" = \"1\";\n \"CD_entityName\" = Mutation;\n}, recordType=CD_Mutation>"
)
在这个阶段,我不确定这是否是NSPersistentCloudKitContainer
我的应用程序中的错误,但它肯定会导致数据不可靠。目前我有这些问题:
- 为什么
NSPersistentCloudKitContainer
(特别是由于NSCloudKitMirroringImportRequest
)导入“更新的”记录,而这些记录仅在本地更改?换句话说:我已经有了最新版本的记录。由于那些“更新”的记录具有过时的值,这会覆盖我的新更改,从而导致数据丢失。跳过这些更新将解决我的问题。有没有办法控制这种行为? - 似乎(显式)更改数据和(隐式)同时镜像它们会导致问题。在我的情况下,由于
NSPersistentCloudKitContainer
在应用程序激活或退出时安排了镜像过程,这会自动发生。有没有办法控制这种行为?例如,我可以在应用程序激活或退出时禁用镜像过程吗?我注意到NSCloudKitMirroringDelegateOptions
默认为automaticallyScheduleImportAndExportOperations:YES
. 我可以改变这个吗?在不太可能发生数据突变的时刻,我是否也可以自己显式地触发镜像过程?
最后,可以在没有连接到 Internet 时(因此,CloudKit 无法镜像数据),事情按预期工作。