繁体   English   中英

如何处理访问同一个 CoreData 存储的多个小部件实例?

[英]How do I deal with multiple widget instances accessing the same CoreData store?

背景资料

我有一个主应用程序,它将单个条目写入应用程序组中包含的数据库(我们分别称它们为“DB1”和“Group1”)。 在同一个项目中,我添加了一个 iOS 14 主屏幕小部件扩展。 然后将此扩展添加到 Group1。

所有三种尺寸(小、中、大)都显示来自 DB1 条目的相同信息,只是重新排列,对于较小的小部件,省略了一些部分。

问题

问题是,如果我有多个小部件实例(比如小型和中型),那么当我重建目标并加载/运行时,我会收到 CoreData 错误,如下所示:

<NSPersistentStoreCoordinator: 0x---MEM--->: Attempting recovery from error encountered during addPersistentStore: Error Domain=NSCocoaErrorDomain Code=134081 "(null)" UserInfo={NSUnderlyingException=Can't add the same store twice}

相关代码

这是时间线 function 的代码

public func timeline(with context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        //Set up widget to refresh every minute
        let currentDate = Date()
        let refreshDate = Calendar.current.date(byAdding: .minute, value: 1, to: currentDate)!
        
        WidgetDataSource.shared.loadTimelineEntry { entry in
            guard let e = entry else { return }
            let entries: [TimelineEntry] = [e]

            let timeline = Timeline(entries: entries, policy: .after(refreshDate))
            completion(timeline)
        }
    }

这是 loadTimelineEntry function

(persistentContainer 在 WidgetDataSource 的 init() 中初始化,class 包含 loadTimelineEntry 函数)

func loadTimelineEntry(callback: @escaping (TimelineEntry?) -> Void) {
        persistentContainer.loadPersistentStores(completionHandler: { (storeDescription, error) in
            print("Loading persistent stores")
            var widgetData: [WidgetData]
            if let error = error {
                print("Unresolved error \(error)")
                callback(nil)
            } else {
                let request = WidgetData.createFetchRequest()
                do {
                    widgetData = try self.persistentContainer.viewContext.fetch(request)
                    guard let data = widgetData.first else { callback(nil); return }
                    print("Got \(widgetData.count) WidgetData records")
                    let entry = TimelineEntry(date: Date())
                    callback(entry)
                } catch {
                    print("Fetch failed")
                    callback(nil)
                }
            }
        })
    }

老实说,我尝试过的东西不多。 在将小部件放入 Group1 之前,我遇到了同样的错误。 那是因为主应用程序在第一次运行时已经创建了 DB1,然后在随后的小部件运行中,它查看了它自己的容器,没有找到它,并试图创建它自己的 DB1,而操作系统没有不要因为他们有相同的名字而让它。

小部件是一个相当新的功能,关于这个特定用例的问题并不多,但我敢肯定有人有类似的设置。 任何帮助或提示将不胜感激!

感谢 Tom Harrington 的评论,我能够通过在我的 loadTimelineEntry function 顶部添加一个检查来解决警告,如下所示:

if !persistentContainer.persistentStoreCoordinator.persistentStores.isEmpty {
   //Proceed with fetch requests, etc. w/o loading stores
} else {
   //Original logic to load store, and fetch data
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM