领域迁移导致某些用户间歇性崩溃
Realm migration causing intermittent crashes for some users
我需要向 Realm
添加一个迁移,这是一个我几乎没有使用经验的框架。在 SO 和其他地方搜索之后,我发现我认为这是一种正确的方法。我需要的是向一个对象引入一个 primaryKey
,并且基于现有代码和我在 SO 上找到的内容,我添加了一个单一的迁移。此外,除了强制展开所有内容之外,我还添加了测试以确保 oldObject 在那里,并且它的 属性 实际上是一个强对象。事后看来,我看到了我可能做过的另一项测试,稍后我会附加它。
一个带有此代码的新版本正在 App Store 中分阶段发布,我们大约有一半的用户已经获得它,数百人。
少数用户在 Realm 迁移块中遇到崩溃。我们的 QA 测试了几个用脏的或干净的 Stuff2
对象迁移的案例,没有发生任何奇怪的事情。但是我们总是从最新版本之前的应用程序版本开始,而不是一些旧版本。
下面是最新的代码,migration 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
的任何人的一些评论或建议。
我可能是 mis-reading 问题,所以如果我错过了标记,请添加评论,我会更新答案。
您的 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;主键不能为零并且必须是唯一的,因此应该进行一些错误检查以确保强制执行。
好吧,技术上一个对象的主键可以是零,但同样,为了强制唯一性,它应该是唯一的。
我需要向 Realm
添加一个迁移,这是一个我几乎没有使用经验的框架。在 SO 和其他地方搜索之后,我发现我认为这是一种正确的方法。我需要的是向一个对象引入一个 primaryKey
,并且基于现有代码和我在 SO 上找到的内容,我添加了一个单一的迁移。此外,除了强制展开所有内容之外,我还添加了测试以确保 oldObject 在那里,并且它的 属性 实际上是一个强对象。事后看来,我看到了我可能做过的另一项测试,稍后我会附加它。
一个带有此代码的新版本正在 App Store 中分阶段发布,我们大约有一半的用户已经获得它,数百人。
少数用户在 Realm 迁移块中遇到崩溃。我们的 QA 测试了几个用脏的或干净的 Stuff2
对象迁移的案例,没有发生任何奇怪的事情。但是我们总是从最新版本之前的应用程序版本开始,而不是一些旧版本。
下面是最新的代码,migration 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
的任何人的一些评论或建议。
我可能是 mis-reading 问题,所以如果我错过了标记,请添加评论,我会更新答案。
您的 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;主键不能为零并且必须是唯一的,因此应该进行一些错误检查以确保强制执行。
好吧,技术上一个对象的主键可以是零,但同样,为了强制唯一性,它应该是唯一的。