Core Data Migrations and Cave Monsters

By Josh Wright on September 2011 in tips


Migrating the core data schema on an iOS app is like a monster in a cave. When I walk by, the monster growls and I back off.

Well not today. Today I learned to do a simple migration in an existing core data app and I confirmed what so many others had said.

It's strangely easy to do migrations... once you know how.

Unfortunately I never found anyone that would explain it, so that's what I'm doing here.

The Docs

Here are the Apple docs for running a core data migration.

Somehow I, along with some others, have found these docs both too complicated and short on information.

How it Really Works

First off, I'll assume that you have a working Core Data app that has a "Model.xcdatamodeld" defining the schema and some data in the database.

Step 1) Create Version 2 of the Model

You don't have to start from scratch, and you don't mess with the existing model. Basically you will add a new version (described below) which starts out looking just like the original model.

  1. Click the "Model.xcdatamodeld" file in your XCode project.
  2. Then, in the Editor menu at the top of the screen, choose "Add Model Version..."
  3. Click through the wizard & call the new model whatever you want. I left it as "Model 2"

Step 2) Update the New Model

Now you can change this "Version 2" model however you want.

NOTE: There are some limitations on what is allowed if you want to keep the migration simple - more info here. If you have to do something complicated that requires special processing (like splitting a field) then checkout the apple docs on custom migrations.

Step 3) Choose the Version

This step is critical, and I never found anyone mention it.

When you create "Model 2" it isn't automatically set as the active version. So at this point, if you installed the app on a new device it would still use the old Model. To tell the application you actually want to use "Model 2", you need to set it as the "Current":

  1. Click on "Model.xcdatamodeld"
  2. Show the "Utilities Column" (the right side of the screen)
  3. Show the "File Inspector" (the left tab of the Utilities Column")
  4. Choose "Model 2" under "Versioned Core Data Model" > "Current"

Step 4) Apply the Migration

You're almost there, but you still need to tell the code that it's OK to run the migration.

Find your code that looks like this:

[self.coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];

Right now you don't have any options, but this is where you tell Core Data to run the migrations automatically if needed. Change it to:

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

[self.coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];

And That's It

Next time you run the app, it should automatically add/remove fields/entities to match your new model.