如何执行更好的 SwiftRealm 迁移值

How perform a better SwiftRealm migration value

我在 iOS 和 Android 上使用 Realm Swift 和 Realm-java。我需要实施数据库迁移以更新数据库中的值。 在 Swift 上,迁移按如下方式完成:currentVersion -> latestVersion。在 Android 上:v1 -> v2 -> latestVersion。

以下示例显示 iOS 上的迁移 0 -> 1 和 1 -> 2:

迁移 0 -> 1 :



    /// 将版本 0 迁移到版本 1 的函数。
    /// 创建奇幻电影类别和关联
    ///
    /// - 参数迁移:迁移实例。
    static func migrateFrom0To1(_迁移:迁移){
        // 为 Fantastic 类别添加的电影。
        让 existingFilmToAdd: [String] = ["STAR_WARS", "HARRY_POTTER"]
        // 获取存储的电影。
        var filmToSet:[MigrationObject] = []
        migration.enumerateObjects(ofType: Film.className()) { _, filmDb 在
            让 key = filmDb!["filmKey"] 作为!细绳
            如果 existingFilmToAdd.contains(键) {
                filmToSet.append(电影数据库!)
            }
        }
        // 创建小说类别。
        让 fantasticCategory = migration.create(Category.className())
        fantasticCategory["categoryKey"] = "FANTASTIC"
        fantasticCategory["name"] = "Fantastic"
        fantasticCategory["films"] = 电影集
    }

迁移 0/1 -> 2



    /// 将版本 0 迁移到版本 1 的函数。
    /// 创建奇幻电影类别和关联
    ///
    /// - 参数迁移:迁移实例。
    static func migrateFrom0To1(_迁移:迁移){
        // 为 Fantastic 类别添加的电影。
        让 existingFilmToAdd: [String] = ["STAR_WARS", "HARRY_POTTER"]
        // 创建超人电影
        让超人 = migration.create(Film.className())
        超人["filmKey"] = "SUPERMAN"
        超人["name"] = "Superman"
        超人["time"] = 2
        // 获取存储的电影。
        var filmToSet:[MigrationObject] = []
        migration.enumerateObjects(ofType: Film.className()) { _, filmDb 在
            让 key = filmDb!["filmKey"] 作为!细绳
            如果 existingFilmToAdd.contains(键) {
            filmToSet.append(电影数据库!)
            }
        }
        filmToSet.append(超人)
        // 创建小说类别。
        让 fantasticCategory= migration.create(Category.className())
        fantasticCategory["categoryKey"] = "FANTASTIC"
        fantasticCategory["name"] = "Fantastic"
        fantasticCategory["films"] = 电影集
    }
    
    /// 将版本 1 迁移到版本 2 的函数。
    /// 在精彩类别中添加电影
    ///
    /// - 参数迁移:迁移实例。
    static func migrateFrom1To2(_迁移:迁移){
        // 创建超人电影
        让超人 = migration.create(Film.className())
        超人["filmKey"] = "SUPERMAN"
        超人["name"] = "Superman"
        超人["time"] = 2
        // 获取存储的电影。
        var filmToSet:[MigrationObject] = []
        // 更新奇幻电影
        migration.enumerateObjects(ofType: Category.className()) { _, migrationCategory in
            让 categoryKey = migrationMarket!["categoryKey"] 作为!细绳
            如果类别键 == "FANTASTIC" {
                让 oldFilm = migrationCategory!["films"] 作为!列表
                对于 oldFilm 中的电影 {
                   filmsToSet.append(电影)
                }
                filmsToSet.append(超人)
                迁移类别!["films"] = filmsToSet
            }
        }
    }

这个例子非常简单,因为数据很简单,但是当我们有更多的值要添加和修改时,迁移就会变得越来越复杂。

在 Android 没问题,迁移一个接着一个,因为数据在每个迁移函数结束时在数据库中可用。 swift 上的迁移实施起来越来越复杂。

我想像 Android 迁移一样进行 Swift 迁移 运行。查看文档和不同的票证后,我找不到解决方案。您有解决问题的解决方案或新架构吗?

注意:解决方案必须始终为我提供迁移数据库架构的可能性

您可以使用类似的方式迁移您的领域。

Realm.Configuration.defaultConfiguration = Realm.Configuration(schemaVersion: 2,
                                                migrationBlock: { (migration, oldSchemaVersion) in
                                                    migrate(oldScema: oldSchemaVersion, migration: migration)
                                                })

并且在 migrate(oldScema:, migration:) 函数中,您可以检查旧架构版本并添加相应的操作。例如:

func migrate(oldScema: Int, migration: Migration) {
    if oldScema < 1 {
        // Migrate 0 -> 1
    }

    if oldScema < 2 {
        // Migrate 1 -> 2
    }
    
    // etc for other migrations
}

我找到了答案: 我通过在从 oldSchemaVersion 开始到新 Schema 版本的循环中使用 performMigration 来进行多次小迁移。
</p> <pre><code>/// Define migration block. private let migrationBlock: MigrationBlock = { migration, oldSchemaVersion in switch oldSchemaVersion { case 0: Migrations.migrateFrom0To1(migration) case 1: Migrations.migrateFrom1To2(migration) case 2: Migrations.migrateFrom2To3(migration) case 3: Migrations.migrateFrom3To4(migration) case 4: Migrations.migrateFrom4To5(migration) case 5: Migrations.migrateFrom5To6(migration) default: break } } /// Initialize realm configuration. /// /// - Throws: If error during realm configuration. private func initializeRealm(realmConfiguration: Realm.Configuration?) throws { // Init Realm configuration. var config: Realm.Configuration if realmConfiguration == nil { config = Realm.Configuration(schemaVersion: currentSchemaVersion) // Get current schema version of the database before migration. let oldSchemaVersion = try schemaVersionAtURL(config.fileURL!) print("oldSchemaVersion: \(oldSchemaVersion) currentSchemaVersion: \(currentSchemaVersion)") // Perform all migrations one by one // (old version to new version) and keep last config. if oldSchemaVersion < currentSchemaVersion { for tmpCurrentSchemaVersion in oldSchemaVersion...currentSchemaVersion { config = Realm.Configuration(schemaVersion: tmpCurrentSchemaVersion, migrationBlock: migrationBlock) try! Realm.performMigration(for: config) } } } else { config = realmConfiguration! } self.realm = try! Realm(configuration: config) }