新领域迁移在新应用安装时被调用

New Realm migration gets called on new app installs

我有一个使用 Realm 的应用程序,它目前有两个不同的迁移,我正在处理第三个迁移,但由于某种原因,这个新迁移有一个奇怪的行为。我理解迁移的方式是,新迁移只会 运行 如果以前的模式版本已经存在,否则它们将被忽略,并且将根据模型的结构创建模式。

这是我看到的。

场景 1:工作正常。

如果之前安装了该应用程序,一切正常,新的迁移 3 运行s 并且它完成了它应该做的所有事情,数据成功转换并且一切正常。

情形 2:错误。

如果应用是第一次安装,用户一启动就开始添加数据,下次启动时(第二次调用AppDelegate)应用会崩溃。我放了一个打印语句,它看起来像应用程序第二次启动时的迁移 3 运行s 但不是在第一次启动时。

场景 3:破解后工作正常。

如果应用程序是第一次安装,但这次是用户 不会立即输入任何数据,而是 he/she 终止应用程序,然后再次重新启动应用程序,一切正常,没有错误,可以毫无问题地输入数据。

换句话说,看起来迁移 3 尝试 运行 应用程序第二次启动时发生错误,因为数据库已经具有第一次 运行 的正确模式结构].

错误场景 2:

libc++abi.dylib: terminating with uncaught exception of type NSException

知道为什么迁移 3 运行 会在新安装的第二次启动时出现吗?这似乎不是正常行为,为什么它会 运行 第二次启动而不是第一次启动。

有什么想法吗?

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

            /// Migration 1:
            Realm.Configuration.defaultConfiguration = Realm.Configuration(
                schemaVersion: 1,
                migrationBlock: { migration, oldSchemaVersion in
                    if (oldSchemaVersion < 1) {
                        // configuration for schema 1
                    }
            })        
            /// Migration 2:
            Realm.Configuration.defaultConfiguration = Realm.Configuration(
                schemaVersion: 2,
                migrationBlock: { migration, oldSchemaVersion in
                    if (oldSchemaVersion < 2) {
                        // configuration for schema 2
                    }
            })
            /// Migration 3:
            Realm.Configuration.defaultConfiguration = Realm.Configuration(
                schemaVersion: 3,
                migrationBlock: { migration, oldSchemaVersion in
                    if (oldSchemaVersion < 3) {
                        // configuration for schema 3
                    }
            })
        }
    }

仅供参考 - 我在每次迁移中都有打印,并且在第一次安装应用程序后第二次启动应用程序时仅迁移 3 运行s。

我会先声明这是作为答案发布的,因为它试图验证问题中的代码在 OP 环境之外是否正常运行。

我已经获取了代码并在整个过程中添加了打印语句,因此可以在控制台中轻松地遵循代码流。

我们从删除所有文件开始,以便模拟应用程序的新安装。您的评论说您输入了数据,但这不是全新安装,因为用户还没有任何数据。

这是添加了一些打印语句的重复代码。对我来说,这是一个 macOS 应用程序,但 iOS 应用程序的行为相同。

迁移函数位于AppDelegate中,这样调用

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    func applicationDidFinishLaunching(_ aNotification: Notification) {
        self.doMigrate()

然后是函数

func doMigrate() {

    print("starting schema version: \(Realm.Configuration.defaultConfiguration.schemaVersion)")

    /// Migration 1:
    Realm.Configuration.defaultConfiguration = Realm.Configuration(
        schemaVersion: 1,
        migrationBlock: { migration, oldSchemaVersion in
            print("migration 1")
            if (oldSchemaVersion < 1) {
                print(" old schema < 1, performaing migration")
                // configuration for schema 1
            }
    })

    print("schema is now: \(Realm.Configuration.defaultConfiguration.schemaVersion)")

    /// Migration 2:
    Realm.Configuration.defaultConfiguration = Realm.Configuration(
        schemaVersion: 2,
        migrationBlock: { migration, oldSchemaVersion in
            print("migration 2")
            if (oldSchemaVersion < 2) {
                print(" old schema < 2, performaing migration")
                // configuration for schema 2
            }
    })

    print("schema is now: \(Realm.Configuration.defaultConfiguration.schemaVersion)")

    /// Migration 3:
    Realm.Configuration.defaultConfiguration = Realm.Configuration(
        schemaVersion: 3,
        migrationBlock: { migration, oldSchemaVersion in
            print("migration 3")
            if (oldSchemaVersion < 3) {
                print(" old schema < 3, performaing migration")
                // configuration for schema 3
            }
    })

    print("schema is now: \(Realm.Configuration.defaultConfiguration.schemaVersion)")
}

首先 运行,这是输出,注意没有发生迁移

starting schema version: 0
schema is now: 1
schema is now: 2
schema is now: 3

当代码是运行第二次时,输出是相同的

starting schema version: 0
schema is now: 1
schema is now: 2
schema is now: 3

即使我添加或更改模型、添加或更改数据,输出仍然保持不变 - 除了它确实崩溃,因为如果对象 属性 被删除,它需要迁移。

所以答案是:如果您没有看到相同的行为,则表明您的环境中有其他因素影响了 code/realm 结构。无论是 运行 一次还是 3 次,它的工作方式都是一样的。