问题描述
我需要向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"
}
}
我对此:
-
我的迁移应该寻找一个空字符串:
如果让old = oldobject?[“ primaryKeyTag”]设为?字符串,!old.isEmpty { ... }
-
在某些旧版本和现在之间,
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,但再次强调,唯一性是强制唯一性。