领域迁移不起作用。

22
    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: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/

有什么想法吗?


1
"schemaVersion" 必须大于先前使用的版本。当前模式版本可能大于1?您能否尝试将更大的数字传递给 "schemaVersion" 参数? - kishikawa katsumi
10个回答

14

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

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

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
  }
}

我改为在需要该对象的函数内创建该对象,这本来就是更好的做法。


1
我也可以确认这是我遇到的问题,谢谢! - Luis
1
我也可以确认这一点。 - lwdthe1
1
太感谢了!原来我在启动视图控制器中实例化领域(realm)。我把实例化移动到viewDidAppear中,现在我的迁移正在运行!谢谢 - Nicolai Harbo
1
这个答案恰当地解决了问题并且有效。谢谢。 - user986408

7
只要您仅处于本地开发环境中,我建议重置您的Realm数据库而不是进行迁移。如果您已经发布了另一个模式的应用程序版本,并且想保留用户数据,则迁移是正确的方法。
您可以通过从模拟器或设备中删除应用程序来删除数据库。 或者您可以使用NSFileManager 在访问数据库之前删除Realm文件。
let defaultPath = Realm.Configuration.defaultConfiguration.path!
try NSFileManager.defaultManager().removeItemAtPath(defaultPath)

13
这并没有解决实际问题,而只是建议在生产应用中使用迁移。 - user986408
1
正确。当您更新 Realm 数据库的属性时,而数据库已经保存了一些数据时,通常会发生此错误。在更改数据库属性(例如重命名现有属性或添加新属性)后,Realm 和 Swift 不知道该怎么处理它,因此会出现错误。要修复它,您需要清除数据库 - 最简单的方法是卸载应用程序并再次运行构建。这个解决方案对我起作用了。 - marika.daboja

4

我也遇到了这个问题,尽管我在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
}

3

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

祝你好运


2

您确定已正确更新了架构版本吗?如果在进行更改之前设置了 schemaVersion: 1,则需要将其更改为 2,以便触发迁移。


2

我也经常遇到相同的致命错误。通常情况下,当你对具有“主键”的Realm对象进行更改时会发生这种情况。最快、最简单的解决方法是直接从设备或模拟器中删除该应用程序,然后再次运行你的项目。


1
当你的应用程序在远程用户设备上时怎么办?那时你该怎么做? - lwdthe1

2

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

原始答案翻译成“最初的回答”。

3
当你的应用程序处于生产中时,你不希望告诉所有用户删除并重新安装应用。这是一个不好的做法,应该避免它。 - J Arango
只有在您使用对象插入数据后,更改了该对象的参数,此方法才有效。 - mehdigriche

1
我找到了最佳解决方案:
您需要在willFinishLaunchingWithOptions中的didFinishLaunchingWithOptions之前添加Realm迁移代码
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

    RealmManager.shared.configureRealm()

    return true
}

0
经过大量的调试,我们发现问题是由于我们在通知服务扩展中配置领域的方式导致的,如此建议:https://github.com/realm/realm-swift/issues/4437
当在第一次应用程序启动之前接收到通知时,它会从通知服务扩展升级模式版本,并使用空迁移块。因此,在应用程序启动后,它不会运行预期的迁移块。我们通过在这两个配置之间共享我们的迁移块来解决了这个问题。

0
在我的情况下,更改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
    }

修改这三行代码就可以了。但是我必须重新同步一下我的设备上的东西。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接