首页 > 解决方案 > NSPersistentCloudKitContainer:与 App Extension 共享单个数据库

问题描述

我知道这是一个常见的问题,也许以前被问过很多次。我还知道如何通过启用 App Groups 来使用 Core Data 与 App Extensions 共享单个数据库。我现在使用NSPersistentCloudKitContainer来同步数据(跨 iCloud 设备),效果很好。

但是我想与我的 App Extensions(Today Extension)共享我的数据库,此时 App Groups 将不再有帮助,因为它们是 Apple 描述的不同技术。所以我只是从签名和功能窗格中为容器应用程序和应用程序扩展启用了 iCloud。然后我可以从两个应用容器/扩展访问我的单个数据库,如下所示:

// MARK: - Core Data stack, Shared database
lazy var persistentContainer: NSPersistentCloudKitContainer = {
    let container = NSPersistentCloudKitContainer(name: "MyApp")

    // Spotlight search support and history tracking
    container.persistentStoreDescriptions.forEach {
        $0.setOption(CoreDataSpotlightSearchDelegate.init(forStoreWith: $0, model: container.managedObjectModel), forKey: NSCoreDataCoreSpotlightExporter)
        $0.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
    }
    
    // Load persistent store
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })

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

但是,它仅在设备在线时才有效(这是预期的行为),所以我的问题是:

当设备离线使用时,是否可以在应用程序和扩展程序之间共享我的数据库NSPersistentCloudKitContainer?一些解决方法?

编辑

这是一个非工作版本,我可以访问相同的数据库但没有云同步(没有出现在 CloudKit 仪表板上):

 // MARK: - Core Data stack, Shared database
lazy var persistentContainer: NSPersistentCloudKitContainer = {
    let container = NSPersistentCloudKitContainer(name: "MyApp")
    
    // Shared container support
    if let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.company.MyApp")?.appendingPathComponent("MyApp.sqlite") {
        let persistentStoreDescription = NSPersistentStoreDescription.init(url: url)
        container.persistentStoreDescriptions = [persistentStoreDescription]
    }

    // Spotlight search support and history tracking
    container.persistentStoreDescriptions.forEach {
        $0.setOption(CoreDataSpotlightSearchDelegate.init(forStoreWith: $0, model: container.managedObjectModel), forKey: NSCoreDataCoreSpotlightExporter)
    }
    
    // Load persistent store
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })

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

标签: swiftcore-datatoday-extensionios-app-groupnspersistentcloudkitcontainer

解决方案


要在应用程序和扩展程序之间共享数据库,您需要完全实现持久历史跟踪;它不像启用商店选项那么简单。有关该功能的介绍,请参阅WWDC 2017 What's New in Core Data at 20:49,另请参阅文档Consuming Relevant Store Changes,特别是“Merge Relevant Transactions into a Context”。

我关于为什么您在使用时没有注意到问题的理论NSPersistentCloudKitContainer是,当您的商店在线并与云同步时,您受益于云同步在您的应用程序进程中运行并在恢复时编辑商店的副作用turn 导致您的上下文得到更新。

顺便说一句,该NSPersistentHistoryTrackingKey选项默认设置为NSPersistentCloudKitContainer具有cloudKitContainerOptions与默认第一个商店描述类似的商店描述。


推荐阅读