iOS:Realm的数据迁移
本地迁移
先看一个例子:
假设我们有如下 Person 模型:
@interface Person : RLMObject
@property NSString *firstName;
@property NSString *lastName;
@property int age;
@end
【iOS:Realm的数据迁移】假如我们想要更新数据模型,给它添加一个 fullname 属性, 而不是将“姓”和“名”分离开来。
@interface Person : RLMObject
@property NSString *fullName;
@property int age;
@end
在这个时候如果您在数据模型更新之前就已经保存了数据的话,那么 Realm 就会注意到代码和硬盘上数据不匹配, Realm 就会抛出错误。这时,您必须进行数据迁移以适应新的对象。
迁移方法:
// 此段代码位于 [AppDelegate didFinishLaunchingWithOptions:]RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
// 设置新的架构版本。必须大于之前所使用的版本
// (如果之前从未设置过架构版本,那么当前的架构版本为 0)
config.schemaVersion = 1;
// 设置模块,如果 Realm 的架构版本低于上面所定义的版本,
// 那么这段代码就会自动调用
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
// 我们目前还未执行过迁移,因此 oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// enumerateObjects:block: 方法将会遍历
// 所有存储在 Realm 文件当中的 `Person` 对象
[migration enumerateObjects:Person.className
block:^(RLMObject *oldObject, RLMObject *newObject) {// 将两个 name 合并到 fullName 当中
newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@",
oldObject[@"firstName"],
oldObject[@"lastName"]];
}];
}
};
[RLMRealmConfiguration setDefaultConfiguration:config];
// 现在我们已经通知了 Realm 如何处理架构变化,
// 打开文件将会自动执行迁移
[RLMRealm defaultRealm];
属性重命名: 下面是一个例子,展示了您该如何在realm中将 Person 的 yearsSinceBirth 属性重命名为 age 属性:
// 此段代码位于 [AppDelegate didFinishLaunchingWithOptions:]RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.schemaVersion = 1;
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
// 我们目前还未执行过迁移,因此 oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// 重命名操作必须要在 `enumerateObjects:` 调用之外进行
[migration renamePropertyForClass:Person.className oldName:@"yearsSinceBirth" newName:@"age"];
}
};
[RLMRealmConfiguration setDefaultConfiguration:config];
线性迁移注意事项
假如说,我们的应用有两个用户: JP 和 Tim。JP 经常更新应用,但 Tim 却经常跳过某些版本。所以 JP 可能下载过这个应用的每一个版本,并且一步一步地跟着更新构架:第一次下载更新后,数据库架构从 v0 更新到 v1;第二次架构从 v1 更新到 v2…以此类推,井然有序。相反,Tim 很有可能直接从 v0 版本直接跳到了 v2 版本。 因此,您应该使用非嵌套的 if (oldSchemaVersion < X) 结构来构造您的数据库迁移模块,以确保无论用户在使用哪个版本的架构,都能完成必需的更新。
当您的用户不按套路出牌,跳过有些更新版本的时候,另一种情况也会发生。假如您在 v2 里删掉了一个 “email” 属性,然后在 v3 里又把它重新引进了。假如有个用户从 v1 直接跳到 v3,那 Realm 不会自动检测到 v2 的这个删除操作,因为存储的数据架构和代码中的架构吻合。这会导致 Tim 的 Person 对象有一个 v3 的 email 属性,但里面的内容却是 v1 的。这个看起来没什么大问题,但是假如两者的内部存储类型不同(比如说: 从 ISO email 标准格式变成了自定义格式),那麻烦就大了。为了避免这种不必要的麻烦,我们推荐您在 if (oldSchemaVersion < 3) 语句中,清空所有的 email 属性。
参考文档:
Realm官方中文文档
Realm官方英文文档
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量