Swift Realm升级出现破坏性变更,自定义User类冲突该如何解决?
问题结论&解决方案
1. 崩溃原因确认
你猜测的原因是正确的:直接重命名自定义User类后,Realm默认会将新类名识别为全新的数据库表,原有存储在User表中的数据不会自动映射到新类上。你读取时获取到的要么是未持久化的临时对象,要么是空对象,对象没有关联任何Realm实例,因此触发assert(object.realm != nil)崩溃。
2. 数据迁移相关方案
不需要复杂的数据迁移,有两种轻量方案可以解决:
- 方案一(无需调整版本号,无迁移流程):在你重命名后的自定义用户类中,重写类名映射方法,让新类仍然关联旧的
User表:
public final class 你的新类名: Object { // 加这一行即可 override public static func className() -> String { "User" } // 原有属性、逻辑保持不变 }
- 方案二(同步修改表名,需要升级版本号):如果你要将数据库中的表名也同步改为新的类名,需要做轻量迁移:
- 将Realm配置的
schemaVersion加1 - 在迁移块中添加类重命名逻辑:
let config = Realm.Configuration( schemaVersion: 你的新版本号, // 比之前的版本号+1 migrationBlock: { migration, oldSchemaVersion in if oldSchemaVersion < 你的新版本号 { migration.renameObjectType(from: "User", to: "你的新类名") } } ) Realm.Configuration.defaultConfiguration = config - 将Realm配置的
3. 改Pod分支的方案说明
该方案技术上可行,但非常不推荐:
- 你需要长期维护Realm的自定义分支,后续升级Realm版本时会产生大量合并成本
- 如果你后续使用Realm Sync、Atlas App Service等功能,修改
typealias User = RLMUser会导致官方相关逻辑出错,排查成本极高
更优的命名冲突解决办法(无需改自己的类,也无需改Realm代码)
Swift原生支持通过模块名区分同名类型,完全可以不修改任何现有命名:
- 用到Realm提供的User类型时,写
Realm.User - 用到你自定义的User类型时,写
你的项目target名.User
如果觉得每次写模块名麻烦,可以在全局头文件或者pch中加自定义别名:typealias AppUser = 你的项目target名.User
后续项目全局用AppUser指代自定义用户类即可,无需修改原有类的定义。
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

