ios - CloudKit 公共(public)记录和更改未下载

标签 ios xcode cloudkit

未下载 CloudKit 公共(public)记录和更改

我有一个 CloudKit 应用程序,其中包含公共(public)和自定义私有(private)记录 区。我似乎有适用于自定义的更改 token 流程 私有(private)区域,但无法使公共(public)数据正常工作。我是代码 除了公共(public)/私有(private)之外,两个数据库的使用是相同的 名称并使用公众的默认区域。我明白那个 订阅不适用于默认区域,但我找不到任何 引用公共(public)数据更改 token 的限制。 Xcode 10.1、iOS 12.0

我创建我的 PubicData 类并初始化它:

    var publicDatabase : CKDatabase!

init() {
    let kAppDelegate = UIApplication.shared.delegate as! AppDelegate
    context = kAppDelegate.context
    let container = CKContainer.default()
    publicDatabase = container.publicCloudDatabase
}//init

从应用入口场景调用的下载函数 - 一个tableview:

func downloadPublicUpdates(finishClosure : @ escaping(UIBackgroundFetchResult) -> Void) {

    var listRecordsUpdated : [CKRecord] = []
    var listRecordsDeleted : [String : String] = [:]

    var publicChangeToken : CKServerChangeToken!
    var publicChangeZoneToken : CKServerChangeToken!

    let userSettings = UserDefaults.standard

    if let data = userSettings.value(forKey: "publicChangeToken") as? Data {
        if let token = try? NSKeyedUnarchiver.unarchivedObject(ofClass : CKServerChangeToken.self, from : data) {
            publicChangeToken = token
            print("publicChangeToken exists")
        }
    } else {
        print("userSettings entry for publicChangeToken does not exist")
    }//if let data

    if let data = userSettings.value(forKey: "publicChangeZoneToken") as? Data {

        if let token = try? NSKeyedUnarchiver.unarchivedObject(ofClass: CKServerChangeToken.self, from: data) {
            publicChangeZoneToken = token
        }

    }//if let data

    let zone = CKRecordZone.default()
    var zonesIDs : [CKRecordZone.ID] = [zone.zoneID]

    let operation = CKFetchDatabaseChangesOperation(previousServerChangeToken: publicChangeToken)

    operation.recordZoneWithIDChangedBlock = {(zoneID) in
        zonesIDs.append(zoneID)
    }

    operation.changeTokenUpdatedBlock = {(token) in
        publicChangeToken = token
    }

    operation.fetchDatabaseChangesCompletionBlock = {(token, more, error) in
        if error != nil{
            finishClosure(UIBackgroundFetchResult.failed)
        } else if !zonesIDs.isEmpty {
            publicChangeToken = token

            let configuration = CKFetchRecordZoneChangesOperation.ZoneConfiguration()
            configuration.previousServerChangeToken = publicChangeZoneToken

            let fetchOperation = CKFetchRecordZoneChangesOperation(recordZoneIDs: zonesIDs, configurationsByRecordZoneID: [zonesIDs[0] : configuration])

            fetchOperation.recordChangedBlock = {(record) in
                listRecordsUpdated.append(record)
            }//fetchOperation.recordChangedBlock

            fetchOperation.recordWithIDWasDeletedBlock = {(recordID, recordType) in
                listRecordsDeleted[recordID.recordName] = recordType
            }//fetchOperation.recordWithIDWasDeletedBlock

            fetchOperation.recordZoneChangeTokensUpdatedBlock = {(zoneID, token, data) in
                publicChangeZoneToken = token
            }//fetchOperation.recordZoneChangeTokensUpdatedBlock

            fetchOperation.recordZoneFetchCompletionBlock = {(zoneID, token, data, more, error) in

                if let ckerror = error as? CKError {
                    self.processErrors(error: ckerror)

                } else {
                    publicChangeZoneToken = token

                    self.updateLocalRecords(listRecordsUpdated : listRecordsUpdated)
                    self.deleteLocalRecords(listRecordsDeleted : listRecordsDeleted)
                    listRecordsUpdated.removeAll()
                    listRecordsDeleted.removeAll()

                }//if else
            }//fetchOperation.recordZoneFetchCompletionBlock

            fetchOperation.fetchRecordZoneChangesCompletionBlock = {(error) in
                if error != nil {
                    print("Error fetchRecordZoneChangesCompletionBlock")
                    finishClosure(UIBackgroundFetchResult.failed)
                } else {

                    if publicChangeToken != nil {
                        if let data = try? NSKeyedArchiver.archivedData(withRootObject: publicChangeToken, requiringSecureCoding: false) {
                            userSettings.set(data, forKey : "publicChangeToken")
                        }
                    }//if changeToken != nil

                    if publicChangeZoneToken != nil {
                        if let data = try? NSKeyedArchiver.archivedData(withRootObject: publicChangeZoneToken, requiringSecureCoding: false) {
                            userSettings.set(data, forKey : "publicChangeZoneToken")
                        }
                    }
                    //self.updateInterface()
                    self.updateLocalReferences()
                    finishClosure(UIBackgroundFetchResult.newData)
                }
            }//fetchOperation.fetchRecordZoneChangesCompletionBlock

            self.publicDatabase.add(fetchOperation)

        } else {//else if !zonesIDs.isEmpty
            finishClosure(UIBackgroundFetchResult.noData)
        }//if zoneid not empty

    }//fetchDatabaseChangesCompletionBlock

    print("listRecordsUpdated.count is \(listRecordsUpdated.count)")

    publicDatabase.add(operation)

}//downloadPublicUpdates

类外:var PD = PDData()

我从初始TableViewController调用viewDidLoad中的download方法:

    PD.downloadPublicUpdates { (result) in
        print("in ctvc viewDidLoad and downloadPublicUpdates")

        switch result {
        case .noData:
            print("no data")
        case .newData:
            print("new data")
        case .failed:
            print("failed to get data")
        }//switch

    }//downloadPublicUpdates

控制台输出始终是:

publicChangeToken 的 userSettings 条目不存在 listRecordsUpdated.count 为 0 在 ctvc viewDidLoad 和 downloadPublicUpdates 中 获取数据失败

如有任何指导,我们将不胜感激。

最佳答案

公共(public)数据库中没有可用的更改 token 。这些仅存在于私有(private)和共享数据库中。

为了保持同步,您通常必须在本地保留记录的修改日期,然后使用 CKQueryOperation 在 CloudKit 服务器上查询更新的内容。

祝你好运!

关于ios - CloudKit 公共(public)记录和更改未下载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53344681/

相关文章:

ios - 如何在 Objective C 中从 uiwebview 保存 pdf

ios - 如果用户没有应用程序,如何实现 DeepLinking?

iphone - 将新电话号码添加到联系人应用程序

ios - CloudKit/火力地堡 : is it possible to send not only push when a record changes but also mail?

ios - CloudKit 订阅未在 iOS10 上保存

ios - 遇到 CKSubscription 错误 : "Cannot create or modify field ' notif_num_subtitle_loc_args'"

ios - 在 Swift 中将 PaintCode 代码插入 UIImageView

ios - 多部分请求 - 使用 UIImage 进行编码的结构

ios - 不兼容的 block 指针类型 | Xcode 6.4 | iOS 8.4

ios - 运行目标“我的 Mac”对于运行方案 'My-iOS-App' 无效