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



背景信息

我有一个主应用程序,它向应用程序组中包含的数据库写入一个条目(我们将分别称它们为"DB1"one_answers"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}

相关代码

这是时间轴功能的代码

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函数

(persistentContainer在WidgetDataSource的init((中初始化,该类包含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函数的顶部添加一个检查来解决警告,如下所示:

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

最新更新