NSPersistentCloudKitContainer data loss edge case

Hi,

I was testing the new iOS 18 behavior where NSPersistentCloudKitContainer wipes the local Core Data store if the user logs out of iCloud, for privacy purposes.

I ran the tests both with a Core Data + CloudKit app, and a simple one using SwiftData with CloudKit enabled. Results were identical in either case.

In my testing, most of the time, the feature worked as expected. When I disabled iCloud for my app, the data was wiped (consistent with say the Notes app, except if you disable iCloud it warns you that it'll remove those notes). When I re-enabled iCloud, the data appeared. (all done through the Settings app)

However, in scenarios when NSPersistentCloudKitContainer cannot immediately sync -- say due to rate throttling -- and one disables iCloud in Settings, this wipes the local data store and ultimately results in data loss.

This occurs even if the changes to the managed objects are saved (to the local store) -- it's simply they aren't synced in time.

It can be a little hard to reproduce the issue, especially since when you exit to the home screen from the app, it generally triggers a sync. To avoid this, I swiped up to the screen where you can choose which apps to close, and immediately closed mine. Then, you can disable iCloud, and run the app again (with a debugger is helpful). I once saw a message with something along the lines of export failed (for my record that wasn't synced), and unfortunately it was deleted (and never synced).

Perhaps before NSPersistentCloudKitContainer wipes the local store it ought to force sync with the cloud first?

This occurs even if the changes to the managed objects are saved (to the local store) -- it's simply they aren't synced in time.

This is by design. Turning off iCloud for an app is equivalent to signing out of the account.

Perhaps before NSPersistentCloudKitContainer wipes the local store it ought to force sync with the cloud first?

Typically that won't work. By the time an application finds out about an account transition (whether by turning off iCloud for an application or signing out) sync will just fail with CKErrorNotAuthenticated.

If a user writes changes to the app and the app saves those changes to the Core Data store, they should never be permanently deleted just because iCloud was disabled.

It seems quite wrong to me that NSPersistentCloudKitContainer will delete even changes that have not been synced to the cloud.

As a developer, what could I do to ensure this does not occur? I believe it is a bad idea to programmatically switch between NSPersistentContainer and NSPersistentCloudKitContainer (discouraged by Apple) and you lose privacy and security.

NSPersistentCloudKitContainer data loss edge case
 
 
Q