Learning Core Data for iOS: Managed Object Model Migration
Anyone who has never made a mistake has never tried anything new.
In Chapter 2, “Managed Object Model Basics,” the fundamentals of managed object models were introduced, yet you were constrained to just one entity and a few attributes. The next logical step is to add more to the model; however, this requires a number of preliminary steps in order to prevent crashes caused by these changes. This chapter will show how to add model versions and model mappings, as well as demonstrate different migration techniques you can choose when upgrading a model.
Changing a Managed Object Model
As an application evolves, its managed object model will probably need to change, too. Simple changes, such as attribute defaults, validation rules, and fetch request templates can be modified without consequence. Other more structural changes require that persistent stores be migrated to new model versions. If a persistent store doesn’t have the appropriate mappings and settings required to migrate data, the application will crash.
Update Grocery Dude as follows to generate a model incompatibility error:
- Run Grocery Dude once to ensure the existing model has been used to create the persistent store. You should see the words “Successfully added store” in the console log.
- Select Model.xcdatamodeld in Xcode.
- Add a new entity called Measurement.
- Select the Measurement entity and add an attribute called abc. Set its type to String.
- Re-run the application and examine the console log. You should now have generated arguably one of the most common Core Data errors, as shown in Figure 3.1. If this error has not appeared, delete the application and then click Product > Clean and retry from Step 1.
Figure 3.1 Model changes make persistent stores incompatible.
This crash isn’t an issue when an application is in its initial development phase. To get past it, you can just delete the application and run it again. When the application is run for the first time after being deleted, the persistent store will be created based on the latest model. This will make the store compatible with the model, so the application won’t crash anymore. However, it won’t have any old data in it. As such, this scenario is unacceptable for any application already available on the App Store. There are a few approaches to migrating existing persistent stores, and the migration path you choose will be driven by the complexity of the changes and whether or not you’re using iCloud. Whatever you do, you’ll first need to become familiar with model versioning.
Update Grocery Dude as follows to revert to the original model:
- Select Model.xcdatamodeld.
- Delete the Measurement entity.
- Re-run the application, which now should not crash.