views:

57

answers:

3

I'm using Core data in an iOS project. I have the data model setup for automatic data migration whenever I modify entity properties. But I recently made some changes to some entity relationships and now my app crashes with: "Can't find model for source store"

I realize that resetting the app i.e deleting and re-installing will solve this issue, bit I have a live version already, and my users will lose all all their data!

So now I'm trying manual migration, but the iOS docs are not very helpful. For instance, I have this code which I run after creating a model mapping:

NSURL *destinationStoreURL = [NSURL fileURLWithPath:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: @"import.sqlite"]]; NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"db.sqlite"]];

//initialize migration manager
NSMigrationManager *migrationManager = [[NSMigrationManager alloc] initWithSourceModel:[[self persistentStoreCoordinator] managedObjectModel]
                                                                      destinationModel:[[self persistentStoreCoordinator] managedObjectModel]];

//perform migration     
NSError *error = nil;       
NSMappingModel *mappingModel = [NSMappingModel inferredMappingModelForSourceModel:[[self persistentStoreCoordinator] managedObjectModel]
                                                                 destinationModel:[[self persistentStoreCoordinator] managedObjectModel] error:&error];

if (mappingModel == nil) {
    NSLog(@"No Mapping model error %@, %@", error, [error userInfo]);
}

[migrationManager migrateStoreFromURL:sourceStoreURL
                                 type:NSSQLiteStoreType
                              options:nil
                     withMappingModel:mappingModel
                     toDestinationURL:destinationStoreURL
                      destinationType:NSSQLiteStoreType
                   destinationOptions:nil
                                error:&error];  

Running this code works and resets the database, but I cant find my old data, and when I save any new data, I get an error that there is no persistent store!

Does anyone have any ideas?

A: 

Did you set current version from Design Menu? Automatic migration should work after that assuming the options NSMigratePersistentStoresAutomaticallyOption and NSInferMappingModelAutomaticallyOption are set to YES.

Jordan
Automatic migration is not working because I changed relationships in mom file. So the Apple docs are recommending that I do Manual Migration. So I created a Mapping Model, compared source and destination entities. deleted properties that didn't match and then added the manual migration code above (after commenting out lightweight migration). That left me with a new database. So now I can't find the old database!
Kwame
I think I'm setting the Mapping manager and the Migration manager incorrectly. Please have a look at the above code and see what you think. I'm not sure what to use as source model and destination model. Maybe the problem is that I'm using the same model for both! But what is the destination model?
Kwame
A: 

Core Data will first check if your data model is compatible with the current data store but this will not be the case if you've modified the relationships. You need to add a model version first which can be done from Xcode by selecting the data model and then choosing from the menu the option Design>Data Model>Add Model Version. You also need to set the current version of the model.

There is some good resource at Apple regarding the migration.

fredg
Thanks. I think what you're describing is automatic lightweight migration, which I've already tried. It usually gives an error: reason = "Can't find model for source store"; So that led me to try Manual migration.
Kwame
A: 

The guys are right...

If it's not too late, try this: Open your “[your database].xcdatamodel” file. Then (assume you are using Xcode), go to your main menu. Select Design > Data Model > Add Model Version. This creates a new file, in our case, “[your database] 2.xcdatamodel":

Now go to Design > Data Model > Set Current Version. Doing this tells Xcode that this is the database schema that you'll be using. Now make whatever database schema changes you want. Now's probably a good time to make any code changes where your database schema change has been directly effected.

Now compile your program. This time it should load.

I encountered the same trouble. This is the first time I've actually read the IPhone Development Docs. I had to really pay attention. Now I'm all set. I actually chose lightweight migration. This code was hijacked straight from one (or several) of Apple's example programs (which often has bugs, just so you'll know... :-/ )

 - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
 if (persistentStoreCoordinator != nil) {
    return persistentStoreCoordinator;
 }

 NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory]
      stringByAppendingPathComponent:DATABASENAME]];
 NSError *error;
 persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:      
  [self managedObjectModel]];

 // Allow inferred migration from the original version of the application.
 NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
        [NSNumber numberWithBool:YES], 
        NSMigratePersistentStoresAutomaticallyOption,
        [NSNumber numberWithBool:YES], 
         NSInferMappingModelAutomaticallyOption, nil];

 //ATTENTION: YOU WERE CRASHING HERE...
 if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
 configuration:nil URL:storeUrl options:options error:&error]) {
       // Handle the error.
      NSLog(@"WTF??? FAILED to create automatic lightweight migration. Error[%@]", error);
 }    
Coach Roebuck