I have had the same problem with CKDatabaseSubscription, as have many others:
I am listing some caveats first in case they explain your issue:
- subscriptions often do not appear in "Developer" CloudKit dashboard (they exist, but are not shown - easiest way to test is rename subscription and see if CloudKit complains about duplicate subscriptions)
- push notifications are not sent to Simulator
Solution:
What fixed this for me was to create a custom private zone and save all my data to that zone (works in private databases only). Then I receive push notifications on any changes to that zone.
You will need to create the zone (-after- checking for CKAccountStatus = .available and -before- any record saves):
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)
And then use that zone when saving your records:
let record = CKRecord(recordType: "MyRecordType", zoneID: CKRecordZone(zoneName: "MyCustomZone"))
// you can save zone to CKRecordID instead, if you want a custom id
Then skip CKFetchDatabaseChangesOperation (because we already know our zone), and use CKFetchRecordZoneChangesOptions instead:
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)