领域迁移和可选属性

Realm Migration and Optional Properties

我最近将我的 Realm 库从 0.92(我认为)升级到 0.96.2,但我对“可选”属性的新支持遇到了一些麻烦。我也是第一次做迁移,也比较麻烦

新方案需要将单个字段添加到其中一种数据类型,因此我编写了一个迁移,在现有对象上建立这个新 属性:

RLMRealmConfiguration* config = [RLMRealmConfiguration defaultConfiguration];
config.schemaVersion = 1;
config.migrationBlock = ^(RLMMigration* migration, uint64_t oldSchemaVersion)
{
    [migration enumerateObjects:Foo.className
                          block:^(RLMObject* oldObject, RLMObject* newObject) {
                              if (oldSchemaVersion < 1)
                              {
                                newObject[@"user"] = @"";
                              }
                          }];
};
[RLMRealmConfiguration setDefaultConfiguration:config];

但是,一旦代码尝试打开 Realm,我就会收到有关可选 属性 类型的错误消息:

'Migration is required for object type 'Person' due to the following errors:
- Property 'name' has been made optional.
- Property ‘company’ has been made optional.
- Property 'title' has been made optional.
- Property 'phone' has been made optional.
- Property 'email' has been made optional.
- Property 'homeAddress' has been made optional.'

问题 #1 - 由于模型正在从“必需”属性变为“可选”属性,因此可以保证现有对象已经存在一个值;所以我很难理解为什么 需要 进行迁移。

问题 #2 - 我仍然喜欢迁移对象,如果字符串为空,则取消属性,所以我编写了一个迁移:

RLMRealmConfiguration* config = [RLMRealmConfiguration defaultConfiguration];
config.schemaVersion = 1;
config.migrationBlock = ^(RLMMigration* migration, uint64_t oldSchemaVersion)
{
    NSLog(@"RUNNING REALM MIGRATION");

    // ...basic migration of adding a new property (above)

    [migration enumerateObjects:Person.className
                          block:^(RLMObject* oldObject, RLMObject* newObject) {
                              if (oldSchemaVersion < 1)
                              {
                                  if ([oldObject[@"name"] length] == 0)
                                      newObject[@"name"] = nil;
                                  else
                                      newObject[@"name"] = oldObject[@"name"];

                                  // … repeat for other properties
                }
                          }];
};
[RLMRealmConfiguration setDefaultConfiguration:config];

但是,迁移似乎不是 运行; if (oldSchemaVersion < 1) 块内的断点永远不会命中,并且 "RUNNING REALM MIGRATION" 消息永远不会打印。

外面的方块——设置RLMRealmConfiguration——被打在里面application:didFinishLaunchingWithOptions:

问题 #1 默认情况下,所有属性在 0.96 之前的 Realm 版本中指定为 'required'。在 0.96 中,它们默认标记为 'optional'。因此,由于新的基础文件格式发生变化以适应这一点(相对重要的变化),需要进行迁移以将这些以前必需的属性转换为可选属性。

如果您希望根据需要保留这些属性,您可以通过重写 [RLMObject requiredProperties] 方法来定义它。

问题 2 嗯……看样例代码,建议把枚举语句封装在if (oldSchemaVersion < 1)条件块里面,不要反过来。这可能会导致事情发生混乱。您是否尝试过交换它?

如果有帮助请告诉我! :)

问题似乎是我正在使用我的迁移信息设置默认 RLMRealmConfiguration,但 [RLMRealm realmWithPath:] 忽略了默认配置。

而不是使用 realmWithPath:,您可以复制默认配置(包括您的 migrationBlockschemaVersion),设置 path 属性,然后传递给 [RLMRealm realmWithConfiguration:error:]

RLMRealmConfiguration* config = [RLMRealmConfiguration defaultConfiguration];
config.path = file;

NSError* error = nil;                    
RLMRealm* realm = [RLMRealm realmWithConfiguration:config
                                             error:&error];