更新了核心数据模型,没有新版本,如何修复?

Posted

技术标签:

【中文标题】更新了核心数据模型,没有新版本,如何修复?【英文标题】:Updated core data model without new version, how to fix? 【发布时间】:2020-10-24 17:24:46 【问题描述】:

我正在处理应用程序更新,我在我的数据模型中添加和删除了一些属性和实体,而没有创建它的新版本。这是我的第一个应用程序,不幸的是我也没有使用任何版本控制系统。

当用户更新应用程序时,我尝试删除旧的 sqlite 文件并重新创建一个新文件,但它在启动后立即崩溃,因为其中一个新属性返回我最近添加的 nil。

我有一个注册屏幕,所以我想我可以在应用更新时再次显示该屏幕并用新数据填充我的模型,但这也不起作用。作为初学者,我完全迷失了。

场景代理

if !UserDefaults.standard.bool(forKey: K.DefaultKey.firstLaunch) 
        
    UserDefaults.standard.set(true, forKey: K.DefaultKey.firstLaunch)
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController = storyboard.instantiateViewController(withIdentifier: "onboard")
    self.window?.rootViewController = viewController
    self.window?.makeKeyAndVisible()

我要删除和重建的代码

class CoreData 
    static let datamodelName = "DataModel"
    static let storeType = "sqlite"

    static let persistentContainer = NSPersistentContainer(name: datamodelName)
    private static let url: URL = 
        let url = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0].appendingPathComponent("\(datamodelName).\(storeType)")

        assert(FileManager.default.fileExists(atPath: url.path))

        return url
    ()

    static func deleteAndRebuild() 
        try! persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: url, ofType: storeType, options: nil)

        persistentContainer.loadPersistentStores(completionHandler:  (nsPersistentStoreDescription, error) in
            guard let error = error else 
                return
            
            fatalError(error.localizedDescription)
        )
    

应用代理

// MARK: - Core Data stack

lazy var persistentContainer: NSPersistentContainer = 
    let container = NSPersistentContainer(name: "DataModel")
    container.loadPersistentStores(completionHandler:  (storeDescription, error) in
        if let error = error as NSError? 
            CoreDataContext.deleteAndRebuild()
            fatalError("Unresolved error \(error), \(error.userInfo)")
        
        
    )
    return container
    
()

编辑:我通过 momd 文件找到了旧模型的哈希码。我可以使用这些哈希码重新创建旧的数据模型吗?

【问题讨论】:

【参考方案1】:

如果可能,解决此问题的最佳方法是撤消模型更改,以便可以加载当前数据。然后再次正确地进行更改,以便可以进行迁移。你会做类似的事情

    开始使用源代码管理。 撤消最近的更改(我知道您没有版本控制,但您可能知道它们是什么)。 通过仅使用该版本的模型运行应用程序来验证第 1 步,并确保它加载数据而不会崩溃。 创建一个新的模型版本,使其成为当前版本,然后在那里进行更改。然后,Core Data 将尝试将数据迁移到新模型。

[更新] 你的删除和重建代码仍然崩溃的原因是你在删除和重建持久存储之后仍然调用fatalError。如果您已成功恢复,则不应再致电fatalError,因为它的全部目的是使应用程序崩溃。我不知道您对返回 nil 的新属性之一是什么意思。这是新属性的预期,因为它是新属性,因此没有数据。

【讨论】:

旧模型已经在appstore上使用,如果我在向当前用户发布新版本时再次更改,应用程序不会再次崩溃吗?我添加了断点以重建代码,但在该应用程序崩溃之前,由于新添加的属性返回 nil 如果您的应用程序崩溃且未迁移用户数据,则数据仍与旧数据模型匹配。如果这是真的,那么回到旧数据模型并添加迁移不会崩溃。 所以如果我创建一个新版本并用旧属性和实体替换它的第一个版本,那么添加迁移将解决问题,对吗?

以上是关于更新了核心数据模型,没有新版本,如何修复?的主要内容,如果未能解决你的问题,请参考以下文章

确定核心数据模型何时有新版本

核心数据模型版本控制和数据迁移

强制核心数据更新模型

我的核心数据数据模型中的一个实体没有被删除

核心数据:如何处理新版本?

向核心数据实体添加瞬态属性是不是需要新版本模型?