Cat with just one property, namehasClaws to Cat model (no explicit migration code needed)Cat model to Feline with this migration:[migration enumerateObjects:@"Cat"
block:^(RLMObject *oldObject, RLMObject *newObject) {
[migration createObject:Feline.className withValue:oldObject];
}];
*** Terminating app due to uncaught exception 'RLMException', reason: 'Invalid property name 'hasClaws' for class 'Cat'.'Allow for field additions followed by class renames, without crashing for multi-version upgrades (e.g. skipping from v0.1 to v0.3)
If a property was added in v0.2 then the class was renamed in v0.3, it shouldn't crash upgrading from v0.1 -> v0.3
Crash *** Terminating app due to uncaught exception 'RLMException', reason: 'Invalid property name 'hasClaws' for class 'Cat'.'
$ cat Podfile.lock | grep Realm
- Realm (2.10.1):
- Realm/Headers (= 2.10.1)
- Realm/Headers (2.10.1)
- Realm (~> 2.10)
Xcode version: Version 9.2 (9C40b)
iOS/OSX version: confirmed on 11.0, but I think it'll happen on any iOS version
Dependency manager + version:
$ pod --version
1.3.1
This it related to https://github.com/realm/realm-cocoa/issues/2491 which has been stale for ~18 months AFAICT. Would be a nice feature of the renameModelFrom:to: function that it would handle cases like this automatically 馃槃
I work with @tsheaff and we realized there were a couple issues at play.
In the enumerateObjects block, newObject is nil if the file that represents that Realm object no longer exists. That's why we were using oldObject. However... oldObject doesn't contain the property change of hasClaws if we're migrating from an even older version.
Albeit hacky, our solution is to maintain the original Cat model with hasClaws property and use it strictly for the realm migration. This lets us use newObject which has the new property and won't cause the crash we saw above. Everywhere else in our codebase only interacts with Felines
Ideally, we wouldn't have to keep a dead file around.
I'm not sure that there's a great solution to this (other than getting #2491 to actually work). The lack of information about intermediate schema versions that a specific install skipped over makes a lot of things in migrations awkward.
An awkward solution would be to do something like the following:
[migration createObject:Feline.className withValue:@{@"name": oldObject.name,
@"hasClaws": oldObject.objectSchema[@"hasClaws"] ? oldObject[@"hasClaws"] : @NO}]
i.e. provide a dictionary with all of the expected keys, and manually handle missing properties in oldObject.
Tracked in #2491. Closing this.
Most helpful comment
I'm not sure that there's a great solution to this (other than getting #2491 to actually work). The lack of information about intermediate schema versions that a specific install skipped over makes a lot of things in migrations awkward.
An awkward solution would be to do something like the following:
i.e. provide a dictionary with all of the expected keys, and manually handle missing properties in oldObject.