PersistenceController and CloudKit

Hello

I am making a To-Do list app where I use CoreData and CloudKit, the problem is that when I added this line of code

 container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: fileContainer.appendingPathComponent("MJ.sqlite"))]

to the PersistenceController, iCloud syncing stopped working. (I need that line of code in order to permit to extensions to access the CoreData database)

Any idea to solve the problem?

This is all the PersistenceController code

struct PersistenceController {
    static let shared = PersistenceController()


    let container: NSPersistentCloudKitContainer

    init(inMemory: Bool = false) {
        container = NSPersistentCloudKitContainer(name: "MJ")
        
        guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.name") else {
            fatalError("Shared file container could not be created.")
        }
        
        container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: fileContainer.appendingPathComponent("MJ.sqlite"))]
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy

    }
}

Thank you!

Accepted Reply

struct PersistenceController {
    static let shared = PersistenceController()
    
    let container: NSPersistentCloudKitContainer
    
    init() {
        container = NSPersistentCloudKitContainer(name: "MJ")
        
        guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.Jad.MJ")?.appendingPathComponent("MJ.sqlite") else {
            fatalError("Shared file container could not be created.")
        }
        
        
        let storeDescription = NSPersistentStoreDescription(url: fileContainer)
        storeDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        storeDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
        storeDescription.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "YOUR containerIdentifier")
        
        
        container.persistentStoreDescriptions = [storeDescription]
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
        
    }
}

Replies

Not sure what the "right answer" is, but This is how I set mine up.

       let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "APPGROUPID")?.appendingPathComponent("NAME.sqlite")

        let description = NSPersistentStoreDescription(url: url)
        description.shouldMigrateStoreAutomatically = true
        description.shouldInferMappingModelAutomatically = false // yours should probably be true if you're not manually migrating between schema versions
        description.shouldAddStoreAsynchronously = true
        description.isReadOnly = false

        let options = NSPersistentCloudKitContainerOptions(containerIdentifier: "MY IDENTIFIER")
        description.cloudKitContainerOptions = options

        return description

Your code makes CloudKit work but stops the widget extension from connecting to the CoreData Database. Thank you for your time.

  • Hi, Were you able to make it work? I am in same boat and could not find a solution

  • Hi, I still can't find a way to connect the widget to CloudKit

  • However this is my Core Data stack now (I will post it as an answer)

Add a Comment
struct PersistenceController {
    static let shared = PersistenceController()
    
    let container: NSPersistentCloudKitContainer
    
    init() {
        container = NSPersistentCloudKitContainer(name: "MJ")
        
        guard let fileContainer = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.Jad.MJ")?.appendingPathComponent("MJ.sqlite") else {
            fatalError("Shared file container could not be created.")
        }
        
        
        let storeDescription = NSPersistentStoreDescription(url: fileContainer)
        storeDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
        storeDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
        storeDescription.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "YOUR containerIdentifier")
        
        
        container.persistentStoreDescriptions = [storeDescription]
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy
        
    }
}