How to do a lightweight Core Data migration

Why do you need to migrate?

When you release an app and add new features, there will be a time you need to update you persistent store. This is easy to do when you are in a development stage, because you can just delete your app and the persistent store will be re-generated. But when you are live and people have downloaded your app, you need to be careful. They won’t like it if suddenly their saved data has disappeared!

When I released my first app iCapital I learned it the hard way. It was my first time I used Core Data and after releasing version 1.0, I started working on it’s first update with too much enthusiasm … but I forgot to version my persistent store. This resulted in a crash at startup after updating the app. The only option out for current users was to reinstall the game, but that ain’t a great user experience 🙂

Ok … how do you do it?

It isn’t very hard to do, because Core Data is pretty smart to do lightweight migrations as long as your changes comply to a few rules.  For more complex migrations you can setup a  mapping model!

To illustrate the process, I’ve put up a sample project which you can get at GitHub.
There are 3 branches:

  1. V1: Initial project with 1 entity Student and 2 properties (firstname, lastname)
  2. V2: First update, added an extra property (email)
  3. V3: Second update: added an extra entity Group with 1 property and 1 relation (has many). Updated the Student entity with also 1 relation to the group.

The steps

Is it a lightweight migration?

You need to be sure that what you are going to change to your data model is actually a lightweight migration? These are the rules:

  • Add an entity
  • Remove an entity
  • Rename an entity
  • Add an attribute / relationship
  • Remove an attribute / relationship
  • Rename an attribute / relationship
  • Make an attribute / relationship optional
  • Make an attribute / relationship not optional, but provide a default value!

So if your model changes comply to these rules, you are good to go for a lightweight migration. If not, you have to setup a mapping model!

Create a new version of your model

Every time you update something in your model, you need to create a new version.
Go to Editor <  Add model version and follow the wizard.

You can now do the changes in the new model.

Use the new model

The current data model being used is being marked with the little green check icon.
Currently your old model will still be active.
To changed this, just click on the top level data model (DevineStudents.xcdatamodeld in the example) and go to your File inspector. In the Versioned Core Data Model section, you can select the new model from the drop down list.

The migration code

The last step is to tell the persistent store that you want to perform a lightweight migration.
Go to your AppDelegate persistentStoreCoordinator setter function and create a dictionary with 2 keys and set them to YES

  1. NSMigratePersistentStoresAutomaticallyOption
  2. NSInferMappingModelAutomaticallyOption
// Do lightweight migration for version 2 of the app

NSDictionary *migrateOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];

if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:migrateOptions error:&error]){

}
Swift

And that’s it 🙂

I hope this post is a bit more clear than the Apple documentation on this subject!
Happy coding!

Share this post

4 Responses

  1. Hi
    Thanks a lot, i do have some queries light weight migration works perfectly fo me but the problem is i don’t want to loose all the data what the user had in there previous DB

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts