Hi Ziqiao, thanks for the reply. Let me explain the situation I'm facing with my CloudKit-powered app.
- Device A and B are both fully synced with the cloud.
- On Device A, the user deletes a bunch of records and continues to use the app, letting the app sync in the background.
- The user waits a few weeks before opening the app on Device B. When they open the app, it attempts to sync. The change token is expired, so it retrieves all of the records on the server.
- My app is designed to treat this as if this is the user's first sync (a "unify" sync), so it compares all records on the server with all local records, then uploads any local records missing from the cloud and downloads any cloud records missing from the local database.
- At this point, all of the items deleted in step 2 have been re-downloaded onto Device B.
Currently, my app never checks deletedRecordIDs on a unify sync. An easy fix would be to start processing this array even on unify syncs. But from your reply, it sounds like this will be an empty array on Device B because the deletions happened on Device A.
Is that true? If so, how can I resolve this problem? Unfortunately, it's somewhat common for my users to have a second device that they use very infrequently, and they get annoyed when previously deleted records re-appear on their second device.
To make my question more concrete, here's some CloudKit code demonstrating the scenario:
// device A
let newRecord = CKRecord(recordType: "Entry",
recordID: CKRecord.ID(recordName: "test"))
newRecord["name"] = "Length"
try await self.database.save(newRecord)
// device B
let (_, _, savedChangeToken, _) =
try await self.database.recordZoneChanges(inZoneWith: self.zoneID, since: nil)
// successfully receives the Entry record with id "test" and saves locally
// we also persist savedChangeToken somewhere on device B
// device A
try await self.database.deleteRecord(withID: CKRecord.ID(recordName: "test"))
// several weeks pass
// device B (uses savedChangeToken from above, which has now expired)
let (_, deletions, _, _) =
try await self.database.recordZoneChanges(inZoneWith: self.zoneID, since: savedChangeToken)
// is the following true or false?
deletions.map(\.recordID).contains(CKRecord.ID(recordName: "test"))
If it's false, how do I resolve the problem described above (deleted records re-appearing on the rarely-used device)?