【问题标题】:CoreData: This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operationCoreData:这个 NSPersistentStoreCoordinator 没有持久存储。它无法执行保存操作
【发布时间】:2020-05-30 08:30:53
【问题描述】:

上周,当我打开我的应用程序并且应用程序尝试在上下文中进行任何保存操作时,我每天都会遇到一次或两次此问题,但我仍然找不到重现它的方法。

我搜索了很多关于 SO 的问题以进行修复,但大多数都指向 2 个问题

  1. 核心数据迁移问题(我没有这个问题,因为我在同一型号版本号上。)

  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


【解决方案1】:

在多次浏览我的 AppDelegate 文件后,我发现我在 applicationDidBecomeActive 方法中执行 Core Data 保存操作,该方法在应用程序从挂起状态启动时也会调用。

因此,如果在调用 applicationDidBecomeActive 之前我的 Core Data 堆栈设置关闭未完成,则应用程序将崩溃。

删除后,应用运行良好,没有任何崩溃

【讨论】:

    猜你喜欢
    • 2012-08-18
    • 2016-03-15
    • 2013-03-07
    • 1970-01-01
    • 2016-02-04
    • 2019-11-12
    • 1970-01-01
    • 2014-10-15
    • 2013-04-08
    相关资源
    最近更新 更多