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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With