更新 iOS 核心数据版本以避免崩溃

Update iOS Core Data Version to Avoid a Crash

我更新了我的 iOS 应用程序,其中包括对核心数据模型进行了大量更改。然后在我将新版本上传到 App Store 并且人们开始尝试使用它之后应用程序崩溃了!

我现在明白这是因为用户在他们的设备上使用的是旧的 Core Data 模型,它与新模型不兼容。我读到我应该更新模型版本,所以现在这就是我正在做的。

虽然我读到我应该在进行更改之前更新模型版本,但我对此有点紧张。显然我不能回到过去 - 已经进行了更改,但在我进行更改之前我没有更新外翻。那么现在只更改模型版本并期望它在我的用户设备上正常工作而不会崩溃是否可以,或者还有其他我可以/必须做的事情吗?

实际数据不是很重要,很快就会被替换,所以我不在乎他们是否可以保留数据。我只需要他们能够更新应用程序而不会在他们下次尝试使用它时崩溃。

如果您正在使用任何版本控制系统,您可以检索旧模型并以正确的方式进行操作,请按照此 documentation 进行操作。

为了防止用户应用程序崩溃,您可以删除旧的 sqlite 文件并使用更新后的模型生成一个新文件。

您可以执行与此代码类似的操作。请注意,每次您的应用无法打开它时,这都会清除 sqlite 文件

__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];

if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) 
{
    if(error)
    {
        //Erase old sqlite
        [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];

        //Make new persistent store for future saves 
        if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
            // do something with the error
        }
    }
}

当您对 Core Data 模型进行更改时,您必须在上传新版本之前完成完整的迁移过程。否则它将只对新用户有效,旧用户会崩溃。现在您必须将数据模型迁移到新版本,然后再次上传构建。 这是唯一的解决方案,更多信息请阅读 link :

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmMigrationProcess.html#//apple_ref/doc/uid/TP40004399-CH6-SW1

Swift 3

    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.appendingPathComponent("name.sqlite")
    let walUrl = url.deletingPathExtension().appendingPathExtension("sqlite-wal")
    let shmUrl = url.deletingPathExtension().appendingPathExtension("sqlite-shm")
    do {
        try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
    } catch {
        do {
            try FileManager.default.removeItem(at: url)
            try FileManager.default.removeItem(at: walUrl)
            try FileManager.default.removeItem(at: shmUrl)
            try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
        } catch let error as NSError {
            //handle error
        }
    }