所谓模型升级,是指数据库存储的数据,随着需求的变化,产生了格式的改变。这个时候,由于数据库里有数据,直接修改模型并运行程序,程序就会崩溃,原因是模型发生了变化。
Realm本身提供了模型升级的功能。官方文档的实例也简单易懂。
不过,今天我遇到一个特殊情况,发现需要在升级的时候使用List对象,是不能直接转换的,摸索之后找到解决方案。先看问题。
问题
已有代码
class Item:Object {
@objc dynamic var title = ""
let records = List<Record>()
override class func primaryKey() -> String? {
return "title"
}
}
class Record:Object {
@objc dynamic var id:Int = 1
@objc dynamic var addedDate:Date = Date()
}
新需求需要在Item
中添加一个新的属性@objc dynamic var addedDate:Date = Date()
。
class Item:Object {
@objc dynamic var title = ""
@objc dynamic var addedDate:Date = Date()
let records = List<Record>()
override class func primaryKey() -> String? {
return "title"
}
}
class Record:Object {
@objc dynamic var id:Int = 1
@objc dynamic var addedDate:Date = Date()
}
升级代码如下:
// update realm
let config = Realm.Configuration(
// Set the new schema version. This must be greater than the previously used
// version (if you've never set a schema version before, the version is 0).
schemaVersion: 1,
// Set the block which will be called automatically when opening a Realm with
// a schema version lower than the one set above
migrationBlock: { migration, oldSchemaVersion in
// We haven’t migrated anything yet, so oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// Nothing to do!
// Realm will automatically detect new properties and removed properties
// And will update the schema on disk automatically
migration.enumerateObjects(ofType: Item.className()) { oldObject, newObject in
newObject!["addedDate"] = (oldObject!["records"] as! List<Record>).first?.addedDate ?? Date()
}
}
})
// Tell Realm to use this new configuration object for the default Realm
Realm.Configuration.defaultConfiguration = config
// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
let _ = try! Realm()
运行时程序出错,提示不能将List<DynamicObject>
转换为List<Record>
。
解决
经过查找资料发现,需要将其转化为List<MigrationObject
。代码如下。究其原因,应该是Realm实例还没有创建,任何Realm的对象都是不可用的。(Record
是Object
子类)
// update realm
let config = Realm.Configuration(
// Set the new schema version. This must be greater than the previously used
// version (if you've never set a schema version before, the version is 0).
schemaVersion: 1,
// Set the block which will be called automatically when opening a Realm with
// a schema version lower than the one set above
migrationBlock: { migration, oldSchemaVersion in
// We haven’t migrated anything yet, so oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// Nothing to do!
// Realm will automatically detect new properties and removed properties
// And will update the schema on disk automatically
migration.enumerateObjects(ofType: Item.className()) { oldObject, newObject in
newObject!["addedDate"] = (oldObject!["records"] as? List<MigrationObject>)?.first?["addedDate"] as? Date ?? Date()
}
}
})
// Tell Realm to use this new configuration object for the default Realm
Realm.Configuration.defaultConfiguration = config
// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
let _ = try! Realm()