从Obj-C Realm迁移至RealmSwift:如何动态迁移属性避免硬编码?
动态迁移方案(从Objective-C Realm到RealmSwift)
核心思路:通过Schema元数据自动映射属性
不需要硬编码每个属性,可借助旧对象的Schema元数据遍历所有属性,自动完成值的复制,同时单独处理主键、数据类型变更这类特殊场景。
基础动态迁移代码
migrationBlock: { migration, oldSchemaVersion in if oldSchemaVersion < 1 { migration.enumerateObjects(ofType: Countries.className()) { oldObject, newObject in guard let oldObj = oldObject, let newObj = newObject else { return } // 遍历旧对象的所有属性 for property in oldObj.schema.properties { let propertyName = property.name // 跳过不需要迁移的属性(按需添加) if propertyName == "OldUnusedProperty" { continue } // 处理数据类型变更的特殊情况 if propertyName == "NeedConvertProperty" { // 示例:NSNumber转Swift Int if let oldValue = oldObj[propertyName] as? NSNumber { newObj[propertyName] = oldValue.intValue } continue } // 普通属性直接复制 newObj[propertyName] = oldObj[propertyName] } // 单独处理主键映射(如果新旧模型主键字段/类型不同) // 示例:新模型主键为countryCode,旧模型对应值在Country_Code字段 // newObj["countryCode"] = oldObj["Country_Code"] } } }
关键注意事项
- 主键处理:主键是模型核心标识,若新旧模型的主键字段名或类型不一致,必须手动映射,无法完全自动化。
- 数据类型兼容:基础类型(如
NSString↔String、NSNumber↔Int)Realm会自动兼容,但自定义类型、NSDecimalNumber转Decimal这类特殊场景需手动转换。 - 嵌套对象迁移:嵌套对象可递归遍历其Schema属性,同样实现动态迁移,避免硬编码嵌套字段。
- 属性过滤:新模型删除的旧属性,需在遍历中跳过,避免无效赋值。
通用迁移扩展(可选)
可封装通用方法减少重复代码:
extension Migration { func migrateObject(oldObject: Object, newObject: Object, excludeProperties: [String] = [], typeConverters: [String: (Any?) -> Any?] = [:]) { for property in oldObject.schema.properties { let name = property.name guard !excludeProperties.contains(name) else { continue } if let converter = typeConverters[name] { newObject[name] = converter(oldObject[name]) } else { newObject[name] = oldObject[name] } } } } // 使用示例 migrationBlock: { migration, oldSchemaVersion in if oldSchemaVersion < 1 { migration.enumerateObjects(ofType: Countries.className()) { oldObj, newObj in guard let o = oldObj, let n = newObj else { return } // 定义需要类型转换的属性 let typeConverters: [String: (Any?) -> Any?] = [ "Population": { value in (value as? NSNumber)?.intValue } ] // 执行通用迁移 migration.migrateObject(oldObject: o, newObject: n, excludeProperties: ["OldUnusedProp"], typeConverters: typeConverters) // 主键单独映射 n["countryCode"] = o["Country_Code"] } } }
内容的提问来源于stack exchange,提问作者Vishnu
相关产品推荐
相关产品推荐

