我的问题与“Delta Download”有关,因为它在WWDC 2014 Advanced CloudKit中被命名。
我正在尝试为我的核心数据应用程序进行同步,目前只有iPhone(想想:只有一个设备处于活动状态)。因此,基本上,应用程序会将用户记录存储在云中,从大多数情况下来自同一设备。
我无法理解基于CKFetchRecordChangesOperation
又名Delta Download的自定义区域功能。
我说得对,我们有CKServerChangeToken
来维护同步操作(我的意思是只下载那些由其他设备添加/修改/删除的记录),如WWDC上所示。
但是,我无法理解的是,我们只在CKFetchRecordChangesOperation
之后收到该令牌,当我们将记录保存到云中时,我们没有得到新的令牌。
如果我们使用当前可用的令牌进行获取(因为它仅在获取后更改),我们会收到从之前的保存操作中保存的记录。基本上我们得到了我们设备上已有的保存记录。为什么?我在这里错过了什么?
如果我们将一些数据播种到云(来自设备A),如果设备B正在获取区域记录,那么情况是合理的,但是如果设备A是什么?再次下载所有记录?
我在recordChangeTag
中找到了CKRecord
,这是一个我可以用来解决与本地对象冲突的属性 - 获取的对象(相同或不同版本),如果是这样,有人可以举例说明如何我需要这样做:在第一次将记录保存到CloudKit时将recordChangeTag保存到Core Data还是如何?
缺乏文档令人头疼。
答案 0 :(得分:3)
我找到时间为这个问题写一个答案。我不会深入研究实施,但我会讨论这个概念。
CloudKit提供了一种在设备和CloudKit服务器之间进行数据同步的方法。 我在iPhone和服务器之间使用什么来建立同步过程(再次,如果你有iPhone + iPad应用程序,这个过程需要更多的步骤。):
我在私有云数据库中有自定义区域。 我使用OperationQueue来建立彼此依赖的不同异步进程。有些操作有自己的操作队列。
步骤:
1)检查我的自定义区域是否存在
1.1)如果没有自定义区域
1.2)创建新的自定义区域。 (可选:添加记录)
1.3)刷新区域更改标记
您可以通过以下方式刷新区域更改令牌:执行
CKFetchRecordChangesOperation
,fetchRecordChangesCompletionBlock
返回CKServerChangeToken
使用NSKeyedArchiver将其保存到UserDefaults(例如)。此操作的任务是刷新令牌,并在结束同步过程中执行。
2)如果已经有自定义区域
2.1)使用以前保存的区域更改令牌从区域获取更改。 (CKFetchRecordChangesOperation
)
2.2)更新并删除本地记录。
2.3)刷新区域更改令牌。
2.4)检查本地更改(我正在使用上一个云同步时间戳来检查之后修改了哪些记录)。
2.5)将记录上传到云端套件数据库
2.6)再次刷新区域更改令牌。
我强烈推荐Nick Harris文章系列:https://nickharris.wordpress.com/2016/02/09/cloudkit-core-data-nsoperations-introduction/
您将找到实施和设计概念。值得一读。我希望有人会发现所有这些都有帮助。
答案 1 :(得分:2)
从iOS 13开始,Core Data中有一个超级有用的方法,称为NSPersistentCloudKitContainer。此方法将自动处理所有本地缓存并与私有数据库上的iCloud同步。您只需更改
即可对其进行设置static var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "ShoeTrack")
container.loadPersistentStores(completionHandler: {
(storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
到
static var persistentContainer: NSPersistentCloudKitContainer = {
let container = NSPersistentCloudKitContainer(name: "ShoeTrack")
container.loadPersistentStores(completionHandler: {
(storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
您将必须在项目中修改Core Data Model文件,并选中“在每个配置上与CloudKit一起使用。