NEW: Subscribe to Hacking with Swift+ and accelerate your learning! >>

Best practices when iCloud is full / user disables iCloud storage for your app.

Forums > Swift

I am using an NSPersistentCloudKitContainer to sync data. If a user runs out of storage space, or disables iCloud syncing for my app, it seems like it would be best to switch to just using a local store. However, I can't find any guidance on how to do this.

Is this something that I should just let the NSPersistentCloudKitContainer handle for me? Or is there another solution?

For reference, this is how I am setting up the container in my app delegate (the default setup):

lazy var persistentContainer: NSPersistentCloudKitContainer = {
        let container = NSPersistentCloudKitContainer(name: "TrackerModel")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        container.viewContext.automaticallyMergesChangesFromParent = true
        return container
    }()

   

Hi @wbrennan899 , I am working thru this now for Core Data. I do have this for just CloudKit on another app so hopefully this helps.

First, it comes down to use case. In my other app where it is just CK and no CD I use it track 'free usage' so that it comes across all devices. Here is the error handling on the completion block for save I use but pretty much lock access if I can't track the usage.

    if let cloudError = error as? CKError {

         if cloudError.errorCode == 9 {
                // handle CloudKit access denied by user settings
              self.handleAccessDeniedByUserSettings()

            }  else if cloudError.errorCode == 25 {

                // handle ExceedQuota
                self.handleExceedPrivateCloudQuote()
            }
      }

I am not sure yet on how Core Data reports this because I'm not sure how to induce these conditions with Core Data but hoping any answer you get addresses that.

In my current use case with Core Data I think I should notify the user that they can't share info across devices as a gentle reminder to change their settings. Just not sure if this same logic above works. Thanks

   

UPDATE:

This is not a good solution. You cannot toggle description.cloudKitContainerOptions without reinitializing the NSPersistentCloudKitContainer.

Also in this case:

  1. user initially has CloudSync on and saves data
  2. user turns off CloudSync
  3. user deletes Cloud data through app settings
  4. user turns CloudSync back on

All of the local user data is lost, which was not my intention.

ORIGINAL:

I figured it out! This thread was helpful: https://developer.apple.com/forums/thread/118924

This solution should allow me to start with iCloud sync off, then I should be able to toggle syncing on/ off it by toggling description.cloudKitContainerOptions = nil for the NSPersistentCloudKitContainer somewhere else in the app if the users turns cloud sync on, or they run out of storage space.


lazy var persistentContainer: NSPersistentCloudKitContainer = {
        let container = NSPersistentCloudKitContainer(name: "ModelName")

        container.persistentStoreDescriptions.forEach {description in
            description.cloudKitContainerOptions = nil
            description.setOption(true as NSNumber,
                         forKey: NSPersistentHistoryTrackingKey)
        }

        container.loadPersistentStores(completionHandler: { (storeDescription, error) in            
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })

        container.viewContext.automaticallyMergesChangesFromParent = true
        return container
    }()

   

Hacking with Swift is sponsored by NSSpain

SPONSORED Announcing NSSpain 2020: Remote Edition! An online, continuous conference for iOS developers. We’ll start on Thursday and finish on Friday, with talks, activities, and lots of fun for 36 hours, non-stop. Sound good? Join us!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

Not logged in

Log in
 

Link copied to your pasteboard.