Pedro Carrasco
Pedro Carrasco

Reputation: 158

Core Data database wiped when using NSPersistentCloudKitContainer

I currently have an application that uses Core Data with Apple's NSPersistentCloudKitContainer and I've a 2 users mentioning they lost their data when updating the app - I'm using Lightweight migrations, and the only factor they have in common is: both had no iCloud Storage left.

After further inspection I've noticed that if I go to Settings > iCloud > Disable it for my app, whenever I open my app again all my data will be gone.

As anyone run into this issue? Is this expected? Any way around it?

For reference, here's my setup code:

self.container = NSPersistentCloudKitContainer(name: "DATABASE_NAME")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
    if let error = error as NSError? {
        Crashlytics.crashlytics().record(error: error)
    }

    self.container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    self.container.viewContext.automaticallyMergesChangesFromParent = true
})

Upvotes: 3

Views: 771

Answers (1)

Viktor Gavrilov
Viktor Gavrilov

Reputation: 976

You could add a check for availability of iCloud container:

func isICloudContainerAvailable()-> Bool {
    if let _ = FileManager.default.ubiquityIdentityToken {
        return true
    } else {
        return false
    }
}

Depending on results of the check you could return NSPersistentCloudKitContainer or NSPersistentContainer. You should also turn on NSPersistentHistoryTrackingKey for NSPersistentContainer case:

lazy var persistentContainer: NSPersistentContainer = {
    var container: NSPersistentContainer!
        
    if isICloudContainerAvailable() {
        container = NSPersistentCloudKitContainer(name: "DATABASE_NAME")
    } else {
        container = NSPersistentContainer(name: "DATABASE_NAME")
        let description = container.persistentStoreDescriptions.first
        description?.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    }

    ...

    return container
}

This way if you go to Settings > iCloud > Disable it for the app, data still should be available in the app (it will use NSPersistentContainer). If you enable iCloud back, all changes in the app will also sync.

But in case user manually delete iCloud data for the app in Manage Account Storage, data in the app will be lost, as it said in the alert: "This will delete all data for this app stored on this iPhone and in iCloud". I can't find the way to save local data for such case.

Upvotes: 6

Related Questions