Using Core Data’s automatic migrations to update data

It’s not brilliantly efficient but it does reuse existing importing code and it does work reliably and well.  If I update the app to include new recipes I only want to include them once.  When the app is first launched a preloaded Core Data sqlite file is copied into the Documents directory.  To provide new recipes to existing users I could have included them as a set of chefdoc files to import from the applications bundle but that would be wasteful as they’d already be in the preloaded file.  So, expanding a bit on the previous use of automatic migrations we can use an NSEntityMigrationPolicy just like before, it happens that I have added more information to the DB so I needed one anyway.  Alongside a routine much like the one used previously we can add the following routine:

- (BOOL)endEntityMapping:(NSEntityMapping *)mapping 
                 manager:(NSMigrationManager *)manager 
                   error:(NSError **)error {
    if (![super endEntityMapping:mapping manager:manager error:error]) return NO;

    [self addNewRecipes:manager];
    
    return YES;
}

Inside the addNewRecipes routine we first grab our own NSPersistentStoreCoordinator and NSManagedObjectContexts:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSError *error = nil;
    NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"Chefs_Book" ofType:@"momd"];
    NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
    NSManagedObjectModel *managedObjectModel = [[NSManagedObjectModel alloc] 
                                                initWithContentsOfURL:modelURL];    
    
    NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
    NSString *initialDataPath = [[NSBundle mainBundle]
                                 pathForResource:@"InitialData" ofType:@"sqlite"];
    NSURL *initialStoreURL = [NSURL fileURLWithPath:initialDataPath];
    [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
                                             configuration:nil 
                                                       URL:initialStoreURL 
                                                   options:nil 
                                                     error:&error];
    
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
    [context setPersistentStoreCoordinator:persistentStoreCoordinator];

Don’t forget to drain the pool at the end of the above! We can then set about iterating through the Recipes. I simply build a list of unique ID’s from our preloaded db, compare it to the users database using the passed in NSMigrationManager to reference the destination context like so:

    NSArray *destRecipeUUIDs = [KookaDIS allRecipeUUID:[manager destinationContext]];

Once I’ve got a list of which ones are missing I convert them into the same format that’s used for emailing then use the same routines to import the data that are used when somebody opens a file in the email application or in safari. It’s not the most efficient as images are converted and base64 encoded and decoded etc. but it has two major advantages:

– The routines are proven and reliable.
– I only have one set of bulk import/export routines to maintain should my needs change in the future.

Having said that, the routines involved are recursive, data independent and obey a set of rules passed in to avoid looping recursion so not many data base schema changes will make it throw a fit.

That is the last big bit of code done for the update. To do now is the progress bar code for data updating/import, some polish (simple UI changes like hiding icons instead of deactivating them to fall more inline with apples UI recommendations) then test it for memory likes and finally do end to end tests on hardware. Probably another week so perhaps two weeks until the update is in the store.

This entry was posted in Chef's Book, Programming and tagged , , , . Bookmark the permalink.

2 Responses to Using Core Data’s automatic migrations to update data

Comments are closed.