我时不时会发生 CoreData 崩溃:
对于 CoreData 实现,我主要使用默认实现,并添加一些内容以使其与我的小部件一起使用(使用应用程序组):
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "Main")
if let description = container.persistentStoreDescriptions.first {
description.shouldMigrateStoreAutomatically = true
description.shouldInferMappingModelAutomatically = true
// This was already added to make sure the widget is in read-only mode
if !inMemory && Bundle.main.bundleIdentifier != Constants.appBundleID {
description.isReadOnly = true
}
}
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
} else {
if let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.groupID),
let description = container.persistentStoreDescriptions.first {
description.url = url.appendingPathComponent("Main.sqlite")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
container.loadPersistentStores { storeDescription, error in // Crash happens here
// This is not called
if let error = error {
assertionFailure("Unresolved error \(error.localizedDescription)")
}
}
}
我已经发现了一个非常相似的崩溃(具有类似的堆栈跟踪)here,但我没有使用任何后台线程来访问 PersistenceController,因此该解决方案不符合我的需求。但是,我认为小部件和 iOS 应用程序可能会尝试同时初始化 PersistenceController,从而创建有点类似的死锁场景。
我还找到了 this 并添加了一些代码,这将使小部件中创建的 PersistenceController 成为只读(请参阅评论)。不幸的是,这并没有解决崩溃问题,因为它仍然在发生。
有人知道如何解决这个崩溃吗?
在向 Apple 提交 TSI 后,我得出的结论是,可能是 CoreData 迁移导致了这次崩溃。不知何故,他们可能需要比预期更长的时间并被系统杀死。
对我的情况有帮助的是在 loadPersistentStores 周围添加 performExpiringActivity。
这可能是这样的:
#if WIDGETS || os(macOS)
loadPersistentStores(container: container)
#else
// Ask for additional time before the app gets suspended.
let processInfo = ProcessInfo()
processInfo.performExpiringActivity(withReason: "Load persistent stores") { [self] expired in
guard !expired else {
return
}
self.loadPersistentStores(container: container)
sleep(2)
}
#endif
}
private func loadPersistentStores(container: NSPersistentContainer) {
container.loadPersistentStores { storeDescription, error in
if let error = error {
assertionFailure("Unresolved error \(error.localizedDescription)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
}
performExpiringActivity
在小部件或 macOS 中不起作用,所以我添加了一个检查。我添加了一个自定义 Swift Flag 来确定代码是否在小部件内运行。
自从实施此操作(大约 3-4 周前)以来,我不再遇到崩溃了。