【发布时间】:2020-05-30 08:30:53
【问题描述】:
上周,当我打开我的应用程序并且应用程序尝试在上下文中进行任何保存操作时,我每天都会遇到一次或两次此问题,但我仍然找不到重现它的方法。
我搜索了很多关于 SO 的问题以进行修复,但大多数都指向 2 个问题
核心数据迁移问题(我没有这个问题,因为我在同一型号版本号上。)
-
加载持久存储失败(在我的情况下也不会发生这种情况,因为如果持久容器上的
loadPersistentStores方法失败,我的核心数据堆栈不会初始化主 UI)
我正在使用以下链接中提到的核心数据堆栈设置: https://williamboles.me/progressive-core-data-migration/
这是我的 CoreData 设置类:
lazy var persistentContainer: NSPersistentContainer = {
let persistentContainer = NSPersistentContainer(name: "ABC")
let description = persistentContainer.persistentStoreDescriptions.first
description?.shouldInferMappingModelAutomatically = false //inferred mapping will be handled else where
description?.shouldMigrateStoreAutomatically = false
description?.type = storeType
return persistentContainer
}()
lazy var managedObjectContext: NSManagedObjectContext = {
let context = self.persistentContainer.newBackgroundContext()
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
context.automaticallyMergesChangesFromParent = true
return context
}()
lazy var _managedObjectContext: NSManagedObjectContext = {
let context = self.persistentContainer.viewContext
context.automaticallyMergesChangesFromParent = true
return context
}()
// MARK: - Singleton
private static var privateShared : CoreDataManager?
class func shared() -> CoreDataManager { // change class to final to prevent override
guard let uwShared = privateShared else {
privateShared = CoreDataManager()
return privateShared!
}
return uwShared
}
class func destroy() {
privateShared = nil
}
// MARK: - Init
init(storeType: String = NSSQLiteStoreType, migrator: CoreDataMigratorProtocol = CoreDataMigrator()) {
self.storeType = storeType
self.migrator = migrator
}
// MARK: - SetUp
func setup(completion: @escaping () -> Void) {
loadPersistentStore {
completion()
}
}
// MARK: - Loading
private func loadPersistentStore(completion: @escaping () -> Void) {
migrateStoreIfNeeded {
self.persistentContainer.loadPersistentStores { description, error in
guard error == nil else {
fatalError("was unable to load store \(error!)")
}
completion()
}
}
}
private func migrateStoreIfNeeded(completion: @escaping () -> Void) {
guard let storeURL = persistentContainer.persistentStoreDescriptions.first?.url else {
fatalError("persistentContainer was not set up properly")
}
if migrator.requiresMigration(at: storeURL, toVersion: CoreDataMigrationVersion.current) {
DispatchQueue.global(qos: .userInitiated).async {
self.migrator.migrateStore(at: storeURL, toVersion: CoreDataMigrationVersion.current)
DispatchQueue.main.async {
completion()
}
}
} else {
completion()
}
}
我在 App Delegate 中使用以下代码初始化 Core Data 堆栈:
CoreDataManager.shared().setup {[unowned self] in
self.showMainUI()
}
我的应用程序在加载 Home Controller 后崩溃,并且我的某些代码在某些 NSManagedObject 模型上执行了保存操作
这是我保存到上下文的方式:
let context = CoreDataManager.shared().managedObjectContext // background context
context.performAndWait {
if let entityDescription = NSEntityDescription.entity(forEntityName: Entity_Name, in: context) {
if let runEntityObject = NSManagedObject(entity: entityDescription, insertInto: context) as? MY_Model {
// Create the Object
guard context.hasChanges else { return }
do {
try context.save() // Crashes here once or twice a day :(
}
catch {
print(error.localizedDescription)
}
}
}
}
一些 SO 答案也提到了线程问题,但我使用 performAndWait 块,所以保存发生在同一个队列中
如果有人在这个问题上指出我正确的方向,那将非常有帮助
【问题讨论】:
-
您的代码是否有可能在
loadPersistentStore完成之前尝试保存coreData? -
在核心数据栈设置方法中执行 mainUI() 方法之前,不会执行保存操作
标签: ios swift core-data nspersistentstore