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官方英文文档

    推荐阅读