container.loadPersistentStores 在 PersistenceController 初始化时崩溃

问题描述 投票:0回答:1

我时不时会发生 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 成为只读(请参阅评论)。不幸的是,这并没有解决崩溃问题,因为它仍然在发生。

有人知道如何解决这个崩溃吗?

swift swiftui core-data crash xcode-organizer
1个回答
0
投票

在向 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 周前)以来,我不再遇到崩溃了。

© www.soinside.com 2019 - 2024. All rights reserved.