3

我正在关注关于添加订阅的“CloudKit 最佳实践”WWDC 讨论,这似乎在 iOS10 中发生了变化。

下面的代码返回“成功!”,但是我的“AllChanges”订阅从未出现在 CloudKit 仪表板上的订阅类型中。

我在 Xcode 8 beta 6 上。

    let subscription = CKDatabaseSubscription(subscriptionID:"AllChanges")
    let notificationInfo = CKNotificationInfo()
    notificationInfo.shouldSendContentAvailable = true
    subscription.notificationInfo = notificationInfo

    let operation = CKModifySubscriptionsOperation(subscriptionsToSave: [subscription], subscriptionIDsToDelete: [])
    operation.modifySubscriptionsCompletionBlock =  {
        (modifiedSubscriptions: [CKSubscription]?, deletedSubscriptionIDs: [String]?, error: Error?) -> Void in

        if error != nil {
            print(error!.localizedDescription)
        } else {
            print("Success!")
        }
    }
    operation.qualityOfService = .utility
    privateDatabase.add(operation)
4

1 回答 1

6

我对 CKDatabaseSubscription 也有同样的问题,还有很多其他问题:

我首先列出一些警告,以防他们解释您的问题:

  • 订阅通常不会出现在“开发人员”CloudKit 仪表板中(它们存在,但未显示 - 最简单的测试方法是重命名订阅并查看 CloudKit 是否抱怨重复订阅)
  • 推送通知不会发送到模拟器

解决方案:

为我解决这个问题的是创建一个自定义私有区域并将我的所有数据保存到该区域(仅适用于私有数据库)。然后我会收到有关该区域的任何更改的推送通知。

您将需要创建区域(检查 CKAccountStatus = .available 和 -before- 任何记录保存):

let operation = CKModifyRecordZonesOperation(recordZonesToSave: [CKRecordZone(zoneName: "MyCustomZone")], recordZoneIDsToDelete: nil)
operation.modifyRecordZonesCompletionBlock = { (savedRecordZones: [CKRecordZone]?, deletedRecordZoneIDs: [CKRecordZoneID]?, error: Error?) in
    if let error = error {
        print("Error creating record zone \(error.localizedDescription)")
    }
}
privateDatabase?.add(operation)

然后在保存记录时使用该区域:

let record = CKRecord(recordType: "MyRecordType", zoneID: CKRecordZone(zoneName: "MyCustomZone")) 
// you can save zone to CKRecordID instead, if you want a custom id

然后跳过 CKFetchDatabaseChangesOperation (因为我们已经知道我们的区域),并使用 CKFetchRecordZoneChangesOptions 代替:

let options = CKFetchRecordZoneChangesOptions()
options.previousServerChangeToken = myCachedChangeToken
let operation = CKFetchRecordZoneChangesOperation(
    recordZoneIDs: [myCustomZoneId],
    optionsByRecordZoneID: [myCustomZoneId: options]
)
operation.fetchAllChanges = true
operation.recordChangedBlock = { (record: CKRecord) -> Void in
        ... do something
}
operation.recordWithIDWasDeletedBlock = { (recordId: CKRecordID, recordType: String) -> Void in
        ... do something
}
operation.recordZoneFetchCompletionBlock = { (recordZoneId, changeToken, tokenData, isMoreComing, error) in
    if let error = error {
        print("Error recordZoneFetchCompletionBlock: \(error.localizedDescription)")
        return
    }
    myCachedChangeToken = changeToken
}
privateDatabase?.add(operation)
于 2017-01-03T19:37:40.830 回答