swiftcloudkitckrecordckrecordzone

Should we cache a CKServerChangeToken in CKDatabase and CKRecordZone separately?


In my app I use CloudKit and a user's private CKDatabase to store records. I do fetches for changes when the app starts as it adviced at WWDC 2016.

Firstly, I call the fetchDatabaseChanges(database: CKDatabase, databaseTokenKey: String, completion: @escaping () -> Void) method. Inside this method in changesOperation.fetchDatabaseChangesCompletionBlock I save a CKServerChangeToken to userDefaults for a key : ckDatabaseToken.

I also call the fetchZoneChanges(database: database, databaseTokenKey: databaseTokenKey, zoneIDs: changedZoneIDs, completion in the changesOperation.fetchDatabaseChangesCompletionBlock of the fetchDatabaseChanges method.

In the fetchZoneChanges method there is an operation.recordZoneFetchCompletionBlock. Inside this block we also need to save the value of the token to the UserDefaults. And I'm saving it to another ckZoneToken variable in User Defaults. So inside the fetchZoneChanges I get and save (from/to UserDefaults) the ckZoneToken value, and inside the fetchDatabaseChanges, I get and save (from/to UserDefaults) the ckDatabaseToken value .

Is it the right technique? Or it is better to use only the one variable in both fetchDatabaseChanges and fetchZoneChanges method sto store the value of CKServerChangeToken?

Which will be the best approach?

Swift 3, Xcode 9


Solution

  • I've experimented with both ways and figured out that if we use the one changeToken in user defaults, we get a "Bad sync continuation data" error.

    When I've used 2 separate values to store database changes and zone changes, I have had no errors.

    So, I think that we have to cache a CKServerChangeToken both in CKDatabase and CKRecordZone separately.