gurehbgui
gurehbgui

Reputation: 14694

NSPersistentCloudKitContainer and AppGroups

can someone help me to find out how to use AppGroups with NSPersistentCloudKitContainer? I'm using CoreData in my iOS app and then want to access it in a share extension. My persistence looks like that:

struct PersistenceController {
    static let shared = PersistenceController()

    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext
        
        do {
            try viewContext.save()
        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
        }
        return result
    }()

    let container: NSPersistentCloudKitContainer

    init(inMemory: Bool = false) {
        container = NSPersistentCloudKitContainer(name: "MyApp")
        
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
    }
    
}

How I need to add my "group.com.foo.myapp" App Group here to use it in both App and extension?

Upvotes: 2

Views: 199

Answers (1)

britafilter
britafilter

Reputation: 11

I was trying to solve the same problem and the following worked for me:

  1. Create a NSPersistentStoreDescription with a url pointing to your app group
  2. Set the store description's cloudKitContainerOptions to an an instance initialized with your cloud kit container identifier
  3. Configure how you would like merges to be handled
  4. Assign the store description to your NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
    container = NSPersistentCloudKitContainer(name: "YourDataModel") // Replace with your data model name

    // 1. Configure for App Group
    let groupIdentifier = "group.com.example.MyApp" // Replace with your app group identifier
    let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupIdentifier)
    let storeDescription = NSPersistentStoreDescription(url: sharedContainerURL!.appendingPathComponent("YourDataModel.sqlite")) // Replace with your data model name

    // 2. Configure for CloudKit
    let cloudKitContainerIdentifier = "YourCloudKitContainerID" // Replace with your CloudKit container identifier
    let cloudKitOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: cloudKitContainerIdentifier)
    storeDescription.cloudKitContainerOptions = cloudKitOptions

    // 3. Handle merges
    storeDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    container.viewContext.automaticallyMergesChangesFromParent = true

    // 4. Assign store description
    container.persistentStoreDescriptions = [storeDescription]

    if inMemory {
        container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
    }
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
}

Upvotes: 1

Related Questions