3

iOS10で変更されたように見えるサブスクリプションの追加に関する「CloudKit Best Practices」WWDCの話に従っています。

以下のコードは「Success!」を返しますが、「AllChanges」サブスクリプションが CloudKit ダッシュボードのサブスクリプション タイプに表示されません。

私はXcode 8ベータ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 で同じ問題が発生しました。

問題を説明する場合に備えて、最初にいくつかの警告をリストします。

  • サブスクリプションは多くの場合、「Developer」CloudKit ダッシュボードに表示されません (それらは存在しますが、表示されません。テストする最も簡単な方法は、サブスクリプションの名前を変更し、CloudKit がサブスクリプションの重複について文句を言うかどうかを確認することです)。
  • プッシュ通知が Simulator に送信されない

解決:

これを修正したのは、カスタム プライベート ゾーンを作成し、すべてのデータをそのゾーンに保存することでした (プライベート データベースでのみ機能します)。次に、そのゾーンへの変更に関するプッシュ通知を受け取ります。

ゾーンを作成する必要があります (CKAccountStatus = .available の確認後、およびレコードの保存前)。

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 に答える