I recently upgrade my Realm library from 0.92 (I think) to 0.96.2, but am having some trouble with the new support for ‘optional’ properties. I also need to do a migration for the first time, which is also complicating matters.
The new scheme needed to add a single field to one of the data types, so I coded up a migration that establishes this new property on existing objects:
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];
However, as soon as the code tries to open a Realm, I get an error message about optional property types:
'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.'
Question #1 - Since the model is going from ‘required’ properties to ‘optional’, there’s guaranteed to be a value already present for existing objects; so I’m struggling to see why a migration is required.
Question #2 - I’d still like to migrate the objects, and nil out the properties if the string is empty, so I coded up a migration:
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];
However, the migration doesn’t appear to be run; a breakpoint inside the if (oldSchemaVersion < 1)
block is never hit, and the "RUNNING REALM MIGRATION"
message never prints.
The outer block — setting up the RLMRealmConfiguration
— is hit inside application:didFinishLaunchingWithOptions:
The issue seems to be that I'm setting up the default RLMRealmConfiguration
with my migration info, but [RLMRealm realmWithPath:]
ignores the default configuration.
Instead of using realmWithPath:
, you can copy the default configuration (including your migrationBlock
and schemaVersion
), set the path
property, and pass it to [RLMRealm realmWithConfiguration:error:]
RLMRealmConfiguration* config = [RLMRealmConfiguration defaultConfiguration];
config.path = file;
NSError* error = nil;
RLMRealm* realm = [RLMRealm realmWithConfiguration:config
error:&error];