I've dealt with lightweight migration before as well as mapping basic changes, but I've googled and overflowed and haven't found a similar case where the entity name is staying the same, but the attribute type is changing from int to string (something I'd think would be easily done)
I thought I was on the right track by subclassing NSEntityMigrationPolicy, then I set the custom policy field in the mappingmodel to this subclass (it didn't autocomplete even after an Xcode restart...)
but I see that createDestinationInstancesForSourceInstance is not getting called
Now, because I'm dealing with a custom mapping model and policy should I still have it inferring the mapping model but having Migrate Automatically off in the persistent store?
NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption:@NO,
NSInferMappingModelAutomaticallyOption:@YES};
Any help is greatly appreciated!
I was really hoping in the Attribute Mapping expression I'd be able to do something like $source.incrementer.string :)
You cannot use lightweight migration for this so it is a little bit harder (thanks Apple), but not impossible
step by step in Xcode 7.1:
1. Create the new model version:
.xcdatamodeld
model -> Editor
-> Add model version ...
attribute type
2. Custom Core Data mapping model
New file -> Mapping Model
(Core Data -> Mapping Model)source
(from model) and target
(to model) version of your modelNameToName
. Change value expression of the changed attribute in target entity in this file reflect the one you need to: FUNCTION($entityPolicy, "<*transformingMethodName*>" , $source.<*attributeName*>)
- transformingMethodName: Your custom method that will be called to transform attribute type. (Will define it in the next step - hold on)
- attributeName: your changed attribute name
<*EntityName*>TransformationPolicy
class as a subclass of NSEntityMigrationPolicy
transformingMethodName
you defined above. (Do what you need there to change the attribute type). Make sure you added this method to your header file as well
First, did you try a lightweight migration to see if it would solve this? As far as SQLite is concerned, it doesn't really care that you are changing a int to a varchar and should be able to do it painlessly.
As far as your mapping model, the options in the persistent store will automatically get overridden when Core Data finds a mapping model for that migration. Therefore you do not need to turn off those options.
As for heavy-weight migration, you need to implement several of the lifecycle methods to get it to work properly, implementing just -createDestinationInstancesForSourceInstance...
is probably not sufficient for the class to be properly recognized and used. I would suggest stubbing out all of the methods with breakpoints and follow which ones get called. I have not done a heavy migration in a while so my memory of which methods are required is hazy.
Having said that, doing a heavy migration for this is a VERY expensive way to solve this issue. While it is the right way, it is really not the best way. I would consider doing something else (assuming a lightweight migration doesn't "just work"):
I suggest these options because heavy weight migration is VERY heavy. It will create memory problems, especially if your data store is even remotely large. It will load up two copies of your data model into memory for the migration. Many iOS applications cannot handle that. It is also very slow and can cause launch issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With