Yes, you still need to use a CKServerChangeToken
even if you implement CKQuerySubscription
. This is how a typical (from what I've seen) CloudKit app works to keep its data in sync:
- Fetch on Launch - When the app launches or becomes active again, check your
CKServerChangeToken
and fetch any new data.
- Fetch from Notifications - Update records from background (i.e. silent) push notifications as they come in from your record
CKQuerySubscription
s so that your data fresh.
Apple describes notifications as "best effort" which means sometimes they aren't going to arrive (and believe me, sometimes they don't). So I have found it useful to periodically fetch new changes (like every few minutes) just in case my app missed a change notification.
Here is some sample code of how to register for all changes to a Task
record type:
let subscription = CKQuerySubscription(recordType: "Task", predicate: NSPredicate(value: true), subscriptionID: "subscriptionTask", options: [.firesOnRecordCreation, .firesOnRecordUpdate, .firesOnRecordDeletion])
let info = CKNotificationInfo()
info.shouldSendContentAvailable = true
info.alertBody = "" //This needs to be set to improve notification priority
subscription.notificationInfo = info
let operation = CKModifySubscriptionsOperation(subscriptionsToSave: [subscription], subscriptionIDsToDelete: nil)
operation.modifySubscriptionsCompletionBlock = { subscriptions, subscriptionIDs, error in
//...
}
let container = CKContainer(identifier: "...")
container.privateCloudDatabase.add(operation)
I hope that helps.