Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic Core Data migration fails on Mac OS X 10.5 but not on 10.6 or 10.7

I've got a NSPersistentDocument-based Core Data app that targets 10.5 Leopard and above. I'm about to release an update that makes changes to the data model, and therefore need to migrate existing documents to the new model. The changes are relatively straightforward, and I've created a mapping model for them. Note that I'm not trying to do automatic lightweight migration, I do have a mapping model (lightweight migration isn't supported on Leopard, but my model changes rule it out anyway). In my NSPersistentDocument subclass, I override -configurePersistentStoreCoordinatorForURL... as follows:

- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url
                                           ofType:(NSString *)fileType
                               modelConfiguration:(NSString *)configuration
                                     storeOptions:(NSDictionary *)storeOptions
                                            error:(NSError **)error
{

    NSMutableDictionary *newOptions = (storeOptions ?
                                       [NSMutableDictionary dictionaryWithDictionary:storeOptions] :
                                       [NSMutableDictionary dictionary]);
    [newOptions setObject:(id)kCFBooleanTrue forKey:NSMigratePersistentStoresAutomaticallyOption];
    return [super configurePersistentStoreCoordinatorForURL:url
                                                     ofType:fileType
                                         modelConfiguration:configuration
                                               storeOptions:newOptions
                                                      error:error];

}

This works fine on 10.6 and 10.7. However, on 10.5, the call to [super configurePersistentStore...] throws an exception and fails. The error is:

Error Domain=NSCocoaErrorDomain Code=134020 UserInfo=0x15812d70 "The model configuration used to open the store is incompatible with the one that was used to create the store."

If I instead initiate the migration manually, using this code:

NSArray *bundles = [NSArray arrayWithObject:[NSBundle mainBundle]];
NSManagedObjectModel *sourceModel = [NSManagedObjectModel mergedModelFromBundles:bundles forStoreMetadata:sourceMetadata];
NSManagedObjectModel *destinationModel = [psc managedObjectModel];
NSMappingModel *mappingModel = [NSMappingModel mappingModelFromBundles:bundles forSourceModel:sourceModel destinationModel:destinationModel];   

NSMigrationManager *migrationManager = [[[NSMigrationManager alloc] initWithSourceModel:sourceModel destinationModel:destinationModel] autorelease];
BOOL migrationSuccessful = [migrationManager migrateStoreFromURL:backupURL
                                                            type:NSXMLStoreType 
                                                         options:storeOptions 
                                                withMappingModel:mappingModel
                                                toDestinationURL:url
                                                 destinationType:NSXMLStoreType
                                              destinationOptions:storeOptions
                                                           error:error];

return [psc addPersistentStoreWithType:NSXMLStoreType configuration:configuration URL:url options:storeOptions error:error] != nil;

the migration works OK. However, I'd prefer to use automatic migration, if for no other reason than because it makes for cleaner code. Has anyone seen a similar problem with automatic migration that works on 10.6+ but not on 10.5? My hunch is that it's something fairly simple like the built in migration code can't find the mapping model for some reason, but I can't figure out what it must be.

like image 826
Andrew Madsen Avatar asked Mar 20 '12 17:03

Andrew Madsen


2 Answers

I'm not 100% this relates to your problem, but there is a documented workaround from Apple on how to migrate Core Data models for 10.6 that also must be compatible with 10.5. It appears that a method is missing in 10.5 that 10.6 relies on for migration.

destinationInstancesForSourceRelationshipNamed:sourceInstances:

is the missing method.

Hopefully this helps.

Reference: http://developer.apple.com/library/mac/#/legacy/mac/library/releasenotes/Cocoa/MigrationCrashBuild106Run105/_index.html

like image 56
macandyp Avatar answered Sep 18 '22 06:09

macandyp


NSPersistentStore is the culprit. It does not implement migrationManagerClass until 10.6.

http://developer.apple.com/library/mac/#documentation/cocoa/reference/NSPersistentStore_Class/NSPersistentStore.html

The Apple work around (as you already have used) is to creation the migration manager yourself rather than relying on the NSPersistentStore to provide it.

like image 26
Fruity Geek Avatar answered Sep 21 '22 06:09

Fruity Geek