96

I have read the documentation about automatic /lightweight migration for Core Data models - but I am having problems implementing it.

As I understand it the application should notice that the model it has and the model that exists on a device already are not the same. If you have only added attributes or relationships and similar simple changes then the model should be upgraded automatically.

Any pointers - do I need to set something in Xcode?

shim
  • 7,170
  • 10
  • 62
  • 95
Grouchal
  • 9,683
  • 6
  • 30
  • 45

10 Answers10

138

I've now found out that this is quite simple - once you know where to look.

In my AppDelegate I set-up the NSPersistentStoreCoordinator - and you need to add some options to this to tell it to handle auto-migrate:

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:

[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,

[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

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

if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
    // Handle error
    NSLog(@"Problem with PersistentStoreCoordinator: %@",error);
}

Then you need to do a little trick in xCode:

  1. Select your xcdatamodel file
  2. Select the Design Menu at the top - then Data Model - then choose Add Model Version
  3. Your xcdatamodel file will then get moved into a new directory with the same name as your xcdatamodel file but with the extension xcdatamodeld - there will be a second file in this directory with a 2 in the name. Select the new file and then Design->Data Model->Set Current Version (in Xcode 4 you do this)
  4. If you have already made the changes that have caused your project to be incompatible - take these changes out of the original xcdatamodel file. If you have yet to make the changes - then just edit the 2.xcdatamodel file (the one you just made current version).
  5. Now when you install this version onto a device that has the old model - it will automatically upgrade that model to the new model.

This seems great and as simple as I wanted - but I think you need to be careful during development as you change a model - otherwise you will have to create a new version for each change.

I think what I will do is that I will keep all of the changed files and then once I get ready to deploy my update I'll delete all the in-between files and just deploy with the oldest and latest models.


UPDATE (15/07/2011):

Thanks to @rockstarberlin for pointing out there is updated documentation at apple:

Xcode 4: Setting a Managed Object Model’s Current Version

Update: 8/19/2013 better link:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmModelFormat.html

Cœur
  • 32,421
  • 21
  • 173
  • 232
Grouchal
  • 9,683
  • 6
  • 30
  • 45
  • I'd suggesting reading the Core Data Migration and Versioning Guide, available in the Xcode doc viewer and on developer.apple.com. – Hunter Jun 19 '09 at 15:10
  • 1
    I didn't find the answer in there laid out simply - it took a while to find out how to do this. – Grouchal Jun 19 '09 at 16:03
  • NSInferMappingModelAutomaticallyOption works well, but only for simple mappings, like changing the name of an attribute. For anything more complicated (relationships, removing or adding entities) you will need to add a mapping model. If Xcode complains that NSInferMappingModelAutomaticallyOption is undeclared, add #import to your app delegate header file. – Elise van Looij Sep 29 '09 at 14:13
  • I added some entities to my model and got the infamous "The model used to open the store is incompatible with the one used to create the store" error. Your solution fixed it! Thank you very much! – Karsten Silz Mar 15 '10 at 23:31
  • Thank you very much for this explanation ! It works perfectly ! – Elegya Sep 01 '10 at 18:07
  • Thanks for this post. I'd been reading up on this all day and there was nothing online that directed me to the Data Modelling menus. This worked a treat, and my faith in Core Data has been renewed :) – Steve Neal Oct 09 '10 at 17:58
  • 1
    See Santthosh's answer below if you are getting "can't merge models with two different entities named" error after following these instructions. – benvolioT Nov 17 '10 at 03:26
  • This solution is actually part of XCode 4's implementation of `persistentStoreCoordinator:`, but thanks this open my eyes to what the problem was. – JeroenEijkhof May 30 '11 at 07:16
  • Nice. Im glad apple made this simple. Just wish some of the things they did were more easily discernible. – The Lazy Coder Nov 05 '11 at 00:05
  • @Grouchal Tnx for the help.I followed your suggestions and migrated the DB successfully.But still left with a query.Whenever i make changes to the core Data if a new version to be created then i may end up with many .xcdatamodel files in my source folder.Does this have any other adverse affects in future...My project has a lot dependency on core data..Plz reply earliest possible it really helps me a lot.. – Dinakar Oct 15 '12 at 10:32
  • I already had an app on the store and just few days ago i uploaded a new version of it without adding a new version of coredata file under "editor" tab after making changes to the DB file and thus the app is getting crashed.Now i included a new version of DB file thus able to see two.xcdatamodel files under main xcdatamodeld file.Now if i submit the app with the changes with a new version..will the user able to access the app without a crash..Plz help i am in a great need.. – Dinakar Oct 15 '12 at 14:03
  • @efrank - The only way to 100% answer this is to test! I can't comment on what changes you might have made! – Grouchal Oct 18 '12 at 11:21
  • New location of menu options: Main Menu -> Editor -> Add Model Version. To set the current version, you'll now find that on the right sidebar, under File Inspector tab, a "Model Version" section, with a drop-down list for "Current". – eselk Mar 23 '15 at 16:26
14

This was incredibly helpful. The Apple documentation was -- as usual -- woefully incomplete. I recommend doing a clean build, as I ran into an error "Can't merge models with two different entities xxx" when I first ran after making these changes. The clean build fixed it up.

Scott Means
  • 506
  • 3
  • 6
6

Grouchal's answer is perfect...but if you are still having the "Can't merge models with two different entities xxx" even after cleaning up the build several times...Your might have issues with how the managedObjectModel is being loaded...take at look at this one...which helped me fix it..

core data migration problems

NANNAV
  • 4,718
  • 4
  • 26
  • 48
Santthosh
  • 1,043
  • 1
  • 12
  • 28
3

Also, if you stumbled upon this post, like I did, after getting the "The model used to open the store is incompatible with the one used to create the store" error and you are just debugging using the simulator and wanting to completely replace the old model installed, you can just Reset the Simulator app or deleting your app from the simulator would probably work as well.

It didn't occur to me to try this until reading the posts here, at which point I realized that I had installed the app in the simulator and then subsequently changed the model, causing the aforementioned run-time error.

dreyln
  • 800
  • 7
  • 18
1

I stumbled onto this post because of a different problems, but the error was "The model configuration used to open the store is incompatible with the one that was used to create the store."

Here was my problem and the solution to it. In my model, I was using configurations. I had some of the entities being stored in one file and the others in a second file. (I have some defaults that might periodically need to get downloaded, and it would be an incredible pain to merge them into the whole). Anyhow, I made a new entity. The program seemed to run fine, but whenever I'd quit, I got the above error.

The solution there was to look at my configurations, realize that I had an entity that wasn't currently in any of the configurations, and add it to one. Runs like a dream.

This won't fix the OP's problem. But maybe some frustrated person who lands here via google will be in the boat I was in :)

The Cappy
  • 573
  • 3
  • 8
1

To follow up on Santthosh's answer, figured I'd post the code snippet right here instead. You need to create your managedObjectModel with initWithContentsOfURL: instead of mergedModelFromBundles: otherwise you'll get error:

Can't merge models with two different entities XXX and XXX

If your Model file is named "Model", here's how you create the managedObjectModel:

NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL]; 

Credit to this blog post.

samvermette
  • 39,555
  • 25
  • 108
  • 143
1

the menu in Xcode 4 changed a bit. here´s a description how to do it in Xcode 4:

Xcode 4: Setting a Managed Object Model’s Current Version

rockstarberlin
  • 1,833
  • 1
  • 18
  • 31
1

I've had this issue for years, and I tried all of these answers to no avail. Today I finally figured out what I was doing wrong. Very simple problem, but I overlooked it. When creating a newer version of the data model, if you are ADDING columns make sure to mark them as OPTIONAL. If you do not the simple migration will not work because the new column values will not be filled in.

As soon as I made sure my new columns has "optional" checked, I tried the migration again and it worked.

Brain2000
  • 3,807
  • 2
  • 24
  • 32
0

iOS 4.0+

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
Stian Høiland
  • 3,545
  • 2
  • 25
  • 32
0

Minor edit to @Grouchal's awesome instructions above for Xcode version 5:

Old: 2. Select the Design Menu at the top - then Data Model - then choose Add Model Version

Version 5+: 2. Select the Editor menu, then Add Model Version…, type your Version name and Based on model (select your original model from the list)

PGSeattle
  • 1
  • 2