CloudKit:CKFetchRecordChangesOperation,CKServerChangeToken和Delta Download

时间:2016-05-05 23:02:37

标签: ios synchronization icloud cloudkit nsoperation

我的问题与“Delta Download”有关,因为它在WWDC 2014 Advanced CloudKit中被命名。

我正在尝试为我的核心数据应用程序进行同步,目前只有iPhone(想想:只有一个设备处于活动状态)。因此,基本上,应用程序会将用户记录存储在云中,从大多数情况下来自同一设备。

我无法理解基于CKFetchRecordChangesOperation又名Delta Download的自定义区域功能。

我说得对,我们有CKServerChangeToken来维护同步操作(我的意思是只下载那些由其他设备添加/修改/删除的记录),如WWDC上所示。 但是,我无法理解的是,我们只在CKFetchRecordChangesOperation之后收到该令牌,当我们将记录保存到云中时,我们没有得到新的令牌。

如果我们使用当前可用的令牌进行获取(因为它仅在获取后更改),我们会收到从之前的保存操作中保存的记录。基本上我们得到了我们设备上已有的保存记录。为什么?我在这里错过了什么?

如果我们将一些数据播种到云(来自设备A),如果设备B正在获取区域记录,那么情况是合理的,但是如果设备A是什么?再次下载所有记录?

我在recordChangeTag中找到了CKRecord,这是一个我可以用来解决与本地对象冲突的属性 - 获取的对象(相同或不同版本),如果是这样,有人可以举例说明如何我需要这样做:在第一次将记录保存到CloudKit时将recordChangeTag保存到Core Data还是如何?

缺乏文档令人头疼。

2 个答案:

答案 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一起使用。