领域迁移不起作用

Posted

技术标签:

【中文标题】领域迁移不起作用【英文标题】:Realm Migration doesn't work 【发布时间】:2016-04-08 11:39:35 【问题描述】:
    let config = Realm.Configuration(
        // Set the new schema version. This must be greater than the previously used
        // version (if you've never set a schema version before, the version is 0).
        schemaVersion: 1,

        // Set the block which will be called automatically when opening a Realm with
        // a schema version lower than the one set above
        migrationBlock:  migration, oldSchemaVersion in
            // We haven’t migrated anything yet, so oldSchemaVersion == 0
            if (oldSchemaVersion < 1) 
                // Nothing to do!
                // Realm will automatically detect new properties and removed properties
                // And will update the schema on disk automatically
            
    )

    // Tell Realm to use this new configuration object for the default Realm
    Realm.Configuration.defaultConfiguration = config

    // Now that we've told Realm how to handle the schema change, opening the file
    // will automatically perform the migration
    let realm = try! Realm()

这是放在 application(application:didFinishLaunchingWithOptions:) 中的

在我的测试程序中,我更改了对象中的字段。我想删除数据库中的所有内容,并移至新的字段类型。我已经从文档中复制了上面的代码,但它似乎什么也没做。我仍然收到这些错误:

fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=0 "Migration is required due to the following errors: 
- Property types for 'unit' property do not match. Old type 'string', new type 'int'
- Property 'reps' has been added to latest object model." UserInfo=NSLocalizedDescription=Migration is required due to the following errors: 
- Property types for 'unit' property do not match. Old type 'string', new type 'int'
- Property 'reps' has been added to latest object model.: file   /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-700.1.101.15/src/swift/stdlib/public/core/

有什么想法吗?

【问题讨论】:

schemaVersion 必须大于以前使用的版本。似乎当前架构版本可能大于 1?您可以尝试将更大的数字传递给 schemaVersion 参数吗? 【参考方案1】:

只要您只进行本地开发,我建议您重置您的 Realm 数据库,而不是进行迁移。如果您已经发布了具有另一个架构的应用版本并且想要保留用户数据,那么迁移是您的最佳选择。

您可以通过从模拟器或设备中删除应用程序来删除数据库。 或者,您可以在访问数据库之前使用NSFileManager 删除 Realm 文件。

let defaultPath = Realm.Configuration.defaultConfiguration.path!
try NSFileManager.defaultManager().removeItemAtPath(defaultPath)

【讨论】:

这并没有解决真正的问题,只是建议将迁移用于生产应用程序。 正确.. 当您更新领域数据库的属性而数据库已经保存一些数据时,通常会发生此错误。更改数据库属性后,即。重命名现有属性或添加新属性、领域和 Swift 不知道如何处理它,因此出现错误。要修复它,您需要清除数据库 - 最简单的方法是卸载您的应用程序并再次运行构建。这个解决方案对我有用。【参考方案2】:

我也经常遇到同样的致命错误。 这通常发生在您使用“主键”更改领域对象时。 最快和最简单的解决方法是从设备或模拟器中删除应用程序 - 然后再次运行您的项目。

【讨论】:

当你的应用在远程用户的设备上时怎么样?那你怎么办?【参考方案3】:

您确定正确更新了 schemaVersion 吗?如果您在进行更改之前设置了schemaVersion: 1,则需要将其更改为2 才能触发迁移。

【讨论】:

【参考方案4】:

确保在 application(application:didFinishLaunchingWithOptions:) 中设置迁移配置之前不要尝试实例化 Realm() 实例。当它崩溃时检查执行堆栈以查找哪个实例引发了异常。我遇到了同样的错误,在我的情况下,我的一个视图控制器中的 Realm 实例是在设置迁移块之前实例化的。

祝你好运

【讨论】:

【参考方案5】:

尽管我在 didFinishLaunchingWithOptions 中添加了默认迁移代码,但我遇到了类似的问题,我的应用程序会崩溃

问题是我确实在 first 视图控制器中将 Realm 实例初始化为类级别属性。因此,从我的第一个 ViewController 中删除该类级别领域对象解决了这个问题。

import UIKit
import RealmSwift

class ViewController: UIViewController
  let db = try! Realm() // Removing this solved my issue

  func doSomething()
    let db = try! Realm() // Placed this here instead
  

我改为在需要它的函数内创建对象,无论如何这是一种更好的方法。

【讨论】:

可以确认这也是我遇到的问题,谢谢! 我也可以确认 这救了我!我在我的启动视图控制器中实例化领域。我将实例化移动到 viewDidAppear,现在我的迁移正在运行!谢谢 这个答案正确地解决了这个问题并且有效。谢谢。【参考方案6】:

我找到了最好的解决方案:

您需要在willFinishLaunchingWithOptionsdidFinishLaunchingWithOptions之前添加领域迁移代码

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool 

    RealmManager.shared.configureRealm()

    return true

【讨论】:

【参考方案7】:

从 iPhone 中删除应用并重新安装。效果很好。

【讨论】:

当您有一个应用程序投入生产时,您不想告诉所有用户删除该应用程序并重新安装。这是一种不好的做法,应该避免。【参考方案8】:

尽管我在 didFinishLaunchingWithOptions 中添加了默认迁移代码,但我的应用还是会崩溃

正如这里已经说过的,问题是我在我的第一个视图控制器中将一个 Realm 实例初始化为一个类级别的属性。

但我不能只删除此实例并将其放入 viewDidLoad,因为我需要在多个函数中使用它。

解决方案实际上是添加'lazy'关键字,因此可以在初始化之前完成迁移,正如我在这里找到的:https://www.selmanalpdundar.com/solution-of-realm-migration-error-code-10.html

import UIKit
import RealmSwift

class ViewController: UIViewController 
    lazy var realm = try! Realm() //added lazy and changed let to var

【讨论】:

【参考方案9】:

就我而言,更改 SchemaVersion 有效

    static let SchemeaVersion: UInt64  = 28 // it was 27 previously

    var config = Realm.Configuration(
        // Set the new schema version. This must be greater than the previously used
        // version (if you've never set a schema version before, the version is 0).
        schemaVersion: RealmUtils.SchemeaVersion,
        
        // Set the block which will be called automatically when opening a Realm with
        // a schema version lower than the one set above
        migrationBlock:  migration, oldSchemaVersion in
          //  print(oldSchemaVersion)
            if (oldSchemaVersion < 27)  // THIS WAS 26
              //  print("Hello")
            
    )
    // ? Till the developement process
    // Delete database in version is lesser than 27 // THIS WAS 26 
    if config.schemaVersion < 27  // THIS WAS 26
        config.deleteRealmIfMigrationNeeded = true
    

更改这 3 行有效。但是,我必须重新同步设备中的内容。

【讨论】:

以上是关于领域迁移不起作用的主要内容,如果未能解决你的问题,请参考以下文章

启用迁移不起作用

实体框架代码优先 - 初始代码迁移不起作用

外键代码在 Laravel 8 的迁移中不起作用

Laravel 迁移不起作用

TPC 在代码优先迁移中不起作用

Laravel 迁移外键不起作用