Search code examples
iphonecocoa-touchcore-dataios4migration

Coredata manual migration


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?


Solution

  • 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);
     }