Skip to content

Instantly share code, notes, and snippets.

@cupnoodle
Last active November 13, 2023 15:11
Show Gist options
  • Save cupnoodle/3877af97a16755946894d6aeed6937dd to your computer and use it in GitHub Desktop.
Save cupnoodle/3877af97a16755946894d6aeed6937dd to your computer and use it in GitHub Desktop.
Disable sync of NSPersistentCloudKitContainer at launch, then enable sync later

To disable iCloud sync of core data when the app launches, set the cloudKitContainerOptions to nil for the persistent store.

In your AppDelegate.swift file :

lazy var persistentContainer: NSPersistentCloudKitContainer = {

        let container = NSPersistentCloudKitContainer(name: "your core data container name")
        
        guard let description = container.persistentStoreDescriptions.first else {
            fatalError("###\(#function): Failed to retrieve a persistent store description.")
        }
        
        description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        
        let remoteChangeKey = "NSPersistentStoreRemoteChangeNotificationOptionKey"
        description.setOption(true as NSNumber,
                              forKey: remoteChangeKey)
        
        
        // Set this to nil then it won't sync to iCloud
        // the default value is a container with the same identifier of the app
        description.cloudKitContainerOptions = nil
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        
        container.viewContext.automaticallyMergesChangesFromParent = true
        return container
    }()

Then do your NSOperation stuff to scan / create managed object, when the operation is done, reinitialize the container, this time with iCloud sync capabiliy :

// In your view controller or the operation queue or somewhere
// once the operations are done, 

(UIApplication.shared.delegate as! AppDelegate).persistentContainer = setupSyncContainer()

func setupSyncContainer() -> NSPersistentCloudKitContainer {
    let container = NSPersistentCloudKitContainer(name: "your core data container name")
    
    guard let description = container.persistentStoreDescriptions.first else {
        fatalError("###\(#function): Failed to retrieve a persistent store description.")
    }
    
    description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    
    let remoteChangeKey = "NSPersistentStoreRemoteChangeNotificationOptionKey"
    description.setOption(true as NSNumber,
                          forKey: remoteChangeKey)
    
    // leave the default cloudKitContainerOptions value as it is, then it will sync automatically
    
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        
        if let error = error as NSError? {
            Error("Unresolved error \(error), \(error.userInfo)")
        }
    })
    
    container.viewContext.automaticallyMergesChangesFromParent = true
    return container
}
@rideroliver
Copy link

Hey, hoping you can help, I feel I’ve got 90% of the way to getting togging cloudkit on and off. sometimes it works fine, but others dispite togging cloudkit off and setting cloudKitContainerOptions = nil I still get syncing occurring . Any advice or code examples that might be my errror?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment