Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Old CloudKit Data Repopulating after a Local Reset

We are trying to solve for the following condition with SwiftData + CloudKit:

  1. Lots of data in CloudKit
  2. Perform "app-reset" to clear data & App settings and start fresh.
  3. Reset data models with try modelContext.delete(model:_) myModel.count() confirms local deletion (0 records); but iCloud Console shows expectedly slow process to delete.
  4. Old CloudKit data is returning during the On Boarding process.

Questions:

• Would making a new iCloud Zone for each reset work around this, as the new zone would be empty? We're having trouble finding details about how to do this with SwiftData.

• Would CKSyncEngine have a benefit over the default SwiftData methods?

Open to hearing if anyone has experienced a similar challenge and how you worked around it!

Answered by DTS Engineer in 843111022

SwiftData + CloudKit doesn't expose any CloudKit data structure, and so you will need to purge the data with your own code. Given that today's SwiftData + CloudKit uses NSPersistentCloudKitContainer under the hood, I'd consider the following flow:

  1. Set up an NSPersistentCloudKitContainer instance and use it to load the SwiftData store.

  2. Fetch an object from the store, and retrieve the CloudKit record ID using recordIDForManagedObjectID:. From there, you can grab the record's zoneID.

  3. Call purgeObjectsAndRecordsInZoneWithID:inPersistentStore:completion: with the record zone ID to purge the local and remote data.

  4. Release all the Core Data objects.

With that, you should be able to get an empty store, use it to set up a new SwiftData model container, and start your app from the beginning.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

SwiftData + CloudKit doesn't expose any CloudKit data structure, and so you will need to purge the data with your own code. Given that today's SwiftData + CloudKit uses NSPersistentCloudKitContainer under the hood, I'd consider the following flow:

  1. Set up an NSPersistentCloudKitContainer instance and use it to load the SwiftData store.

  2. Fetch an object from the store, and retrieve the CloudKit record ID using recordIDForManagedObjectID:. From there, you can grab the record's zoneID.

  3. Call purgeObjectsAndRecordsInZoneWithID:inPersistentStore:completion: with the record zone ID to purge the local and remote data.

  4. Release all the Core Data objects.

With that, you should be able to get an empty store, use it to set up a new SwiftData model container, and start your app from the beginning.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Since we are only configuring only 1 zone and the objective is to delete every record, would using modifyRecordZones(saving:deleting:) to simply delete the zone then start our app from the beginning have the same outcome ...

That will work, if there is no synchronization activity happens in between the deletions of the local data and the remote data, which you can probably achieve by releasing the model container immediately after deleting the local data. But again, SwiftData doesn't expose any CloudKit thing, and so I am not quite sure if that is a guarantee.

(and be more Swifty?)

The APIs I mentioned have the Swift version. It seems that the documentation is broken, and so I can only find the links to the objective C version.

Best,
——
Ziqiao Chen
 Worldwide Developer Relations.

Old CloudKit Data Repopulating after a Local Reset
 
 
Q