A Simple Migration

To demonstrate a simple migration, let’s add the ability to attribute recipes to authors. To begin the versioning, the first thing we need to do is create a new managed object model (MOM) based on the first one. To do that, we select the existing model in Xcode and then choose Design > Data Model > Add Model Version.

Creating a Versioned Data Model

images/CurrentV2.png

This is the first time we’ve added a model version, so Xcode is going to create a new bundle for us called PPRecipes.xcdatamodeld and put the original MOM inside the bundle along with a new copy of the original MOM. To make things more clear in the example project, I renamed these MOM objects to v1.xcdatamodel and v2.xcdatamodel. Select the PPRecipes.xcdatamodeld file and open the File Inspector Utility View (1). In the utility view, you’ll see a Versioned Core Data Model section. (The Xcode templates have been bouncing back and forth on this issue over the past few versions. It’s possible, depending on when you created your project, that you already have a versioned data model.) Inside of that section is a Current option, allowing us to select which model file is the current one. Make sure it references v2, as shown in the screenshot.

Now that we have a new version of the MOM, it’s time to add the new entities and attributes. This process requires the addition of a new entity and some changes to the Recipe entity. Comparing the v1 data model and the v2 data model (as shown), you can see that we added a new Author entity along with its one-to-many relationship with the Recipe entity. Also, the Recipe entity has a new attribute called lastUsed, which is defined as a Date.

images/V1vsV2.png

We’re not quite done. If we were to run the application right now, we would trip the error that we discussed in Some Maintenance Before We Migrate. Clearly, something is missing.

Turning On Automatic Data Migration

The first thing we need to do is to tell Core Data to automatically migrate data when the persistent store isn’t using the same model as the current version. To do this, we’ll make a small change to the persistentStoreCoordinator method in our AppDelegate. Previously we were passing nil to the addPersistentStoreWithType:configuration:URL:options:error: method for the options parameter. However, we need to change that to the following:

RecipesV2/PPRecipes/PPRAppDelegate.m
 NSMutableDictionary *options = [NSMutableDictionary dictionary];
 [options setValue:[NSNumber numberWithBool:YES]
  forKey:NSMigratePersistentStoresAutomaticallyOption];
 [options setValue:[NSNumber numberWithBool:YES]
  forKey:NSInferMappingModelAutomaticallyOption];
 
 NSPersistentStore *store = nil;
 store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
  configuration:nil
  URL:storeURL
  options:options
  error:&error];

The first of these options, NSMigratePersistentStoresAutomaticallyOption, tells Core Data to attempt a migration automatically if it determines that one is needed.

The second option, NSInferMappingModelAutomaticallyOption, instructs Core Data to resolve the mapping between the persistent store and the current model. If Core Data can figure this out, it will perform the migration.

For this migration, Core Data can easily resolve the changes that need to be made and will be able to do an inferred (automatic) migration for us. When the changes are more severe, we do a heavy, manual migration, as discussed in A Heavy/Manual Migration.

With those changes made, we can run our application, and Core Data automatically handles the migration for us and updates the persistent store to the new model.