Timering

Purp

CoreData Tutorial Part 5/5 - Model Versioning, Lightweight Migration, Model Mapping

When you need to change your Core Data Entities or structure, you have to add new model version before you send your App in AppStore. If you change just attributes or fetched templates, it’s not needed, you can do it without consequence. But if you want to add a new Entity, you have to migrate your persistent store to a new model version. You should also set mappings for the migration. In this tutorial, we add model versions, model mappings, and using Lightweight Migration.

Steps:

  1. Add New Managed Object Model Versions
  2. Set Lightweight Migration
  3. Add Model Mappings
  4. Test

Part of the series:

  1. “You must to know!” Collection - Core Data simple explanations
  2. Core Data tutorial Part 1 / 5 - Create Managed Object Model with Attributes, Relationships & Delete Rules
  3. Core Data tutorial Part 2 / 5 - Save Entity’s Attributes, Relationships, and make FetchRequest
  4. Core Data tutorial Part 3 / 5 - Edit, Delete NSManagedObjects
  5. Core Data part 4 / 5 - Change Core Data model, using SortDescriptor, NSPredicate FetchRequest and filter Array using Predicate
  6. Core Data tutorial part 4.2 / 5 - Using NSFetchedResultsController, Reorder TableViewCells with LongPressGesture

iCloud Sync tutorials:

  1. iCloud Sync tutorial Part 1/2 - create iCloudStore, check if user is Signed in, migrate store
  2. iCloud Sync tutorial Part 2/2 - soon!

Video tutorial:

1. Managed Object Model Versioning

If you learn CoreData, I’m sure, that you use the “delete App in Simulator before Run” method, when you change your Database and get a crash when trying to run your App in IOS Simulator or on your IOS device. If you work on a real App, and you want to submit it in App Store, you have to use this easy Managed Object Model Versioning method.

1.1. Add new Model

Select your CoreDataTutorial.xcdatamodeld file in your XCode, In “Editor” menu select the “Add Model Version…” submenu.

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 1_1_1

Xcode adds Version name with number 2 automatically. If you use these version names in the future, you can see the changes step by step. The important thing is, the “Based on model” select Field should select the correct actual model version. 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 1_1_2

1.2. Set model version

Select the CoreDataTutorial.xcdatamodeld group, and at the right side set the new version as a current model version

 SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 1_2_1

1.3. Add new Entity 

Named: “Migration”, and a new attribute: “teststring” as a String attribute. 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 1_3_1

1.4. In Editor menu click on “Create NSManagedObject Subclass..”. 

In the pop-up window select the current model versions, than thick only the “Migration” Entity. Not select the “scalar properties for primitive data types”. 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 1_4_1

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 1_4_2

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 1_4_3

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 1_4_4

Probably you will find these line there:

2. LightWeight Migration

For Model Versioning and for Model Mapping you need to use Lightweight Migration. This will be necessary for iCloud sync too.

In Appdelegate.m file created you the NSPersistentStore. Here you need to use NSDictionary to use NSMigratePersistentStoresAutomaticallyOption and NSInferMappingModelAutomaticallyOption Both of them are YES. In this case, the first line helps Core Data automatically migrate the lower-versioned stores to the latest model. NSInferMappingModel helps to Core Data to infer automatically the attributes of source model entities as attributes in the destination model entities.

You can add these options to your PersistentStore with this simple code:

Using those two options together is called lightweight migration.
You should change your - (NSPersistentStoreCoordinator )persistentStoreCoordinator { part of code for this with this NSDictionary line and addPersistentStore **“options:nil” need to change to “options:options”: 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 2_1


Run the App and create some User with type and Hobby: 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 2_2

3. Model Mapping

When you want to say manually, which data from the earlier Model should goes which attributes to the new current model versions, you need to creata Model Mapping and change NSInferMappingModelAutomaticallyOption from YES to NO. Start with this.

3.1. Add a new Model Version and a new Entity

  • Add a new Model Version: CoreDataTutorial 3.
  • Set the Model 3 to the current Model.
  • Add New Entity: MappingHome with an attribute: “ hmname ” as a String attribute.
  • Create NSManagedObjectModel Subclass…

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_1_1

3.2. Create Model Mapping

Select Data Model group, right click, New File and select Mapping Model: 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_2_1

Set CoreDataTutorial 2 as "Source Data" and CoreDataTutorial 3 Model version as "Target Data" Model: 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_2_2

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_2_3

Save with the name: “Model2to3”:

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_2_4

Now you have a Mapping Model: 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_2_5

3.3. Set Source and Destination Data:

Click on Type Entity, and check the right side at the Entity Mapping the Source and Destination Entity names. These are the same. At the typeName attribute, there is a Value Expression: “$source.typeName”, that means, the Destination typeName attribute use the typeName attribute from the source Model’s Type Entity. 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_3_1

Now click on your new Entity. You can see, that MappingHobby hasn’t got Value Expression, that means, no source Data. 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_3_2

But we would like to see here, the old Hobby Entity’s hobbyName attribute data. 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_3_3

Select MappingHobby Entity, at right side select “Hobby” as a Source. Now Your Entity Name changed from “MappingHobby” to “HoobyToMappingHobby”. 

 SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_3_4

Now Add source Value Expression to the “hmname” attribute: “$source.hobbyName”. 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 3_3_5

Probably you will find these line there:

4. Test Model Maping

Yes, we should test it. Go to "ViewController.m" , import  MappingHobby.h”  file. 

SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 4_1

in ViewDidLoad create a FetchRequest for the MappingHobby Entity, and List in NSLog all of the string attribute “hmname” strings, which should be the name of the Hobby Entity. So we call them too:

Run Project —> Clean, then Run the App, and check the log, you should see the Fetched MappingHobby Object names as same as Hobby Object names. 

 SpotlessiCode | IOS Tutorial | Core Data tutorial | Part 5 | Model Versioning | Lightweight Migration | Model Mapping 4_2

Now you are ready to use Model Versioning with Lightweight Migration or create Model Mapping.

Download

Download the Xcode template from Github.

Share & Follow

If you would like to be notified of my new solutions, please subscribe to my Newsletter or my youtube channel and/ or follow me on Facebook or Twitter! Check Footer section for these opportunities!