领域迁移导致某些用户间歇性崩溃

问题描述

我需要向Realm添加迁移,这实际上是我没有经验的框架。在SO和其他地方进行搜索之后,我发现我认为这是正确的方法。我需要为一个对象引入primaryKey,然后根据现有代码和在SO上找到的内容添加一个迁移。另外,除了仅强制展开所有内容外,我还添加了测试以确保oldobject存在,并且其属性实际上很强。事后看来,我可能还会进行另一项测试,稍后再进行补充。

具有此代码的新版本现已在App Store中分阶段发布,我们大约一半的用户已经获得了数百个。

少数用户在Realm迁移块中崩溃。我们的质量检查人员测试了几种使用脏的或干净的Stuff2对象进行迁移的情况,但从未发生过奇怪的事情。但是我们总是从最新版本的App版本开始,而不是较早的版本。

下面是最新的代码,迁移34是我的补充。

private let latestRealmVersion: UInt64 = 34

var config = Realm.Configuration(
    schemaVersion: latestRealmVersion,migrationBlock: { migration,oldSchemaVersion in
        if (oldSchemaVersion < 2) {
            migration.enumerateObjects(ofType: String(describing: Stuff0.self)) { oldobject,newObject in
                newObject!["soMetag"] = ""
            }
        }

        ...

        if oldSchemaVersion < 33 {
            migration.enumerateObjects(ofType: String(describing: Stuff1.self)) { _,newObject in
                newObject!["anotherTab"] = ""
            }
        }

        // My Change
        if oldSchemaVersion < 34 {
            migration.enumerateObjects(ofType: String(describing: Stuff2.self)) { oldobject,newObject in
                if let old  = oldobject?["primaryKeyTag"] as? String {
                    newObject!["primaryKeyTag"] = old
                } else {
                    newObject!["primaryKeyTag"] = "nil"
                }
                //Stuff2 updated with a primary key
            }
        }

config.deleteRealmIfMigrationNeeded = false
Realm.Configuration.defaultConfiguration = config

Stuff2对象被添加primaryKey()

// Older Object
class Stuff2: Object {
    @objc dynamic var primaryKeyTag = ""
    @objc dynamic var localID = ""
    ...
}

// New Object
class Stuff2: Object {
    @objc dynamic var primaryKeyTag = ""
    @objc dynamic var localID = ""
    ...

    override static func primaryKey() -> String? {
        return "localID"
    }
}

我对此:

  1. 我的迁移应该寻找一个空字符串:

    如果让old = oldobject?[“ primaryKeyTag”]设为?字符串,!old.isEmpty { ... }

  2. 在某些旧版本和现在之间,Stuff2对象发生了变化,这现在导致崩溃。我可以看到一个较旧的迁移块,它使用了不正确的迁移类型,即migration.enumerateObjects(ofType: String(describing: SoundsLikeStuff2.self)),可能从未做过任何事情。

我真的可以使用真正认识Realm的人的一些评论或建议。

解决方法

我可能会误读问题,因此如果我错过了分数,请添加评论,我将更新答案。

似乎您有一个没有定义主键的Realm对象

class Stuff2: Object {
    @objc dynamic var primaryKeyTag = ""
    @objc dynamic var localID = ""
}

,然后在某个时候需要一个主键,并且您希望将localID属性设置为该主键,因此您向该对象添加了primaryKey函数(这将触发迁移)

class Stuff2: Object {
    @objc dynamic var primaryKeyTag = ""
    @objc dynamic var localID = ""

    override static func primaryKey() -> String? {
        return "localID"
    }
}

因此,在这种情况下,唯一需要做的就是获取旧的localID值并将其分配给新的localID属性(现在是主键)

let vers = UInt64(1)
let config = Realm.Configuration( schemaVersion: vers,migrationBlock: { migration,oldSchemaVersion in
     if (oldSchemaVersion < vers) {
        migration.enumerateObjects(ofType: TestClass.className()) { oldItem,newItem in

            let oldVar = oldItem!["localID"] as! String
            newItem!["localID"] = oldVar
         }
     }
 })

有两个getcha。主键不能为nil,并且必须是唯一的,因此应该进行一些错误检查以确保强制执行。

好吧,从技术上来说一个对象的主键可能为nil,但再次强调,唯一性是强制唯一性。