When there's a crash in WidgetKit, it often goes unnoticed by developers and users because there's no clear indication within the widget itself. In contrast, a crash in the main app is more apparent because it causes the app to close suddenly.
One theory, as discussed in this https://developer.apple.com/forums/thread/668649, is that the main app and the widget are attempting to perform a migration simultaneously.
However, I'm skeptical of this theory because our last CoreData migration began last year. Therefore, it's surprising to see a high number of crashes after a year.
Here's where fatal error occurs. It is a pretty standard CoreData stack used in widget.
private static func setupNSPersistentContainer() -> NSPersistentContainer {
precondition(Thread.isMainThread)
let container = NSPersistentCloudKitContainer(name: "***", managedObjectModel: NSManagedObjectModel.***)
// Integrate AppGroup with CoreData. If we are assigning a new store description to CoreData, it is important
// to finish all store description initialization, before assigning. If not, CloudKit will not work.
let storeURL = AppGroup.wenote.containerURL.appendingPathComponent(Constants.WENOTE_SQLITE)
let newStoreDescription = NSPersistentStoreDescription(url: storeURL)
// Turn on persistent history tracking.
newStoreDescription.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
newStoreDescription.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
newStoreDescription.cloudKitContainerOptions = nil
// Finalize store description assigning.
container.persistentStoreDescriptions = [newStoreDescription]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// This is a serious fatal error. We will just simply terminate the app, rather than using error_log.
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
Here's the info from XCode's Organizer.
Here's the crash log
Thread 0 name:
Thread 0 Crashed:
0 libswiftCore.dylib 0x000000018d371870 _assertionFailure(_:_:file:line:flags:) + 264 (AssertCommon.swift:144)
1 sticky-note-widgetExtension 0x0000000104dcb890 closure #1 in static CoreDataStack.setupNSPersistentContainer() + 376 (CoreDataStack.swift:76)
2 sticky-note-widgetExtension 0x0000000104dcb8e4 thunk for @escaping @callee_guaranteed (@guaranteed NSPersistentStoreDescription, @guaranteed Error?) -> () + 80 (<compiler-generated>:0)
3 CoreData 0x000000019c14a0ec -[NSPersistentStoreCoordinator _doAddPersistentStoreWithDescription:privateCopy:completeOnMainThread:withHandler:] + 668 (NSPersistentStoreCoordinator.m:1402)
4 CoreData 0x000000019c149df8 -[NSPersistentStoreCoordinator addPersistentStoreWithDescription:completionHandler:] + 228 (NSPersistentStoreCoordinator.m:1448)
5 CoreData 0x000000019c149bf4 -[NSPersistentContainer _loadStoreDescriptions:withCompletionHandler:] + 184 (NSPersistentContainer.m:291)
6 CoreData 0x000000019c219ff0 -[NSPersistentCloudKitContainer _loadStoreDescriptions:withCompletionHandler:] + 536 (NSPersistentCloudKitContainer.m:163)
7 CoreData 0x000000019c0b852c -[NSPersistentContainer loadPersistentStoresWithCompletionHandler:] + 248 (NSPersistentContainer.m:274)
8 sticky-note-widgetExtension 0x0000000104dcbdb0 specialized static CoreDataStack.setupNSPersistentContainer() + 992 (CoreDataStack.swift:73)
9 sticky-note-widgetExtension 0x0000000104dcb5f8 static CoreDataStack.setupNSPersistentContainer() + 4 (CoreDataStack.swift:23)
10 sticky-note-widgetExtension 0x0000000104dcb5f8 closure #1 in CoreDataStack.persistentContainer.getter + 4 (<compiler-generated>:0)
11 sticky-note-widgetExtension 0x0000000104dcb5f8 CoreDataStack.persistentContainer.getter + 36
12 sticky-note-widgetExtension 0x0000000104dcb5a0 CoreDataStack.viewContext.getter + 28
13 sticky-note-widgetExtension 0x0000000104db2058 specialized static NSPlainNoteRepository.getFirstStickyNoteWithoutTrash() + 68 (NSPlainNoteRepository.swift:54)
14 sticky-note-widgetExtension 0x0000000104da4828 static NSPlainNoteRepository.getFirstStickyNoteWithoutTrash() + 8 (NSPlainNoteRepository.swift:22)
15 sticky-note-widgetExtension 0x0000000104da4828 static NSPlainNoteRepository.getStickyNote(_:) + 8 (sticky_note_widget.swift:15)
16 sticky-note-widgetExtension 0x0000000104da4828 Provider.placeholder(in:) + 64 (<compiler-generated>:0)
17 sticky-note-widgetExtension 0x0000000104da4828 protocol witness for IntentTimelineProvider.placeholder(in:) in conformance Provider + 104
18 WidgetKit 0x00000001a2c65a50 IntentTimelineEntryProvider.placeholder(for:with:) + 528 (IntentConfiguration.swift:258)
19 WidgetKit 0x00000001a2c6a2a0 protocol witness for EntryProviding.placeholder(for:with:) in conformance IntentTimelineEntryProvider<A, B> + 24 (<compiler-generated>:0)
20 WidgetKit 0x00000001a2b56ef4 closure #1 in closure #2 in WidgetExtensionXPCServer.ExportedObject.getPlaceholders(requests:completion:) + 2172 (WidgetExtensionXPCServer.swift:250)
21 WidgetKit 0x00000001a2b5659c closure #2 in WidgetExtensionXPCServer.ExportedObject.getPlaceholders(requests:completion:) + 164 (WidgetExtensionXPCServer.swift:219)
22 WidgetKit 0x00000001a2c64054 thunk for @escaping @callee_guaranteed () -> () + 36 (<compiler-generated>:0)
So far, we are not able to reproduce such a crash locally.