I have two model versions - 12 and 13. Then I created a xcmappingmodel-File with source 12 and destination 13.
I subclassed NSEntityMigrationPolicy and added my class to the mappingmodel-File to the entity desired.
@interface EndDateMigrationPolicy : NSEntityMigrationPolicy
After installing and older version (11) on my device, I install the current status with model version 13 - the app runs, but my migration methods aren't called. Am I missing something?
EDIT: is it correct to use these options?
NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption: @YES,
NSInferMappingModelAutomaticallyOption: @YES};
I'm going to try to answer you as best I can, I have suffered through core data migrations quite a few times so I know how painful it is. For one you can not hope to have to have your migration work with those options because what you are trying to do is actually not a lightweight migration and yet you are telling it to do a lightweight migration.
Basically let's say you need for some reason to have a non lightweight migration between 2 versions, in your case 11 and 12. What you will need to do is do:
1->12 lightweight 12->13 custom migration 13->(future version) lightweight migration
There might be a better solution but I have not yet found it.
Here is some code to help you out (the hardest parts, I can't remember everything offhand), before this code I copy the database to a backup, so basically the back up database is your old one and the store is your new one (which is empty)
NSString *path = [[NSBundle mainBundle] pathForResource:<YOUR MODEL NAME> ofType:@"cdm"];
NSURL *backUpURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"<YOUR MODEL NAME>MigrationBackUp.sqlite"]; //or whatever you want to call your backup
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"<YOUR MODEL NAME>.sqlite"];
NSError *err2 = nil;
NSDictionary *sourceMetadata2 =
[NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType
URL:backUpURL
error:&err2];
NSManagedObjectModel *sourceModel2 = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:[NSBundle mainBundle]]
forStoreMetadata:sourceMetadata2];
NSManagedObjectModel *destinationModel2 = [self managedObjectModelForVersion:@"1.4"]; //Yeah your gonna have to get your mapping model , I'll give you this code too later
NSString *oldModel = [[sourceModel2 versionIdentifiers] anyObject];
NSLog(@"Source Model : %@",oldModel);
NSMappingModel *mappingModel = [[NSMappingModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]];
if (mappingModel != nil) {
for (NSString * identifier in [mappingModel entityMappings]) {
NSLog(@"Mapping > %@",identifier);
}
}
Then just make a migrator with your source and destination.
This is also a difficult part afterwards:
BOOL success = [migrator migrateStoreFromURL:backUpURL
type:NSSQLiteStoreType
options:nil
withMappingModel:mappingModel
toDestinationURL:storeURL
destinationType:NSSQLiteStoreType
destinationOptions:nil
error:&err2];
Last but not least (I said I'd give it to you before):
- (NSManagedObjectModel *)managedObjectModelForVersion:(NSString*)version {
NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"];
if (BETWEEN_INEX(version, @"1.0", @"1.4")) {
modelPath = [modelPath stringByAppendingPathComponent:@"Model"];
modelPath = [modelPath stringByAppendingPathExtension:@"mom"];
} else if (BETWEEN_INEX(version, @"1.4", @"1.5")) {
modelPath = [modelPath stringByAppendingPathComponent:@"Model 2"];
modelPath = [modelPath stringByAppendingPathExtension:@"mom"];
} else if (BETWEEN_INEX(version, @"1.5", @"1.6")) {
modelPath = [modelPath stringByAppendingPathComponent:@"Model 3"];
modelPath = [modelPath stringByAppendingPathExtension:@"mom"];
} else if (BETWEEN_INEX(version, @"1.6", @"1.7")) {
modelPath = [modelPath stringByAppendingPathComponent:@"Model 4"];
modelPath = [modelPath stringByAppendingPathExtension:@"mom"];
}
NSURL *modelURL = [NSURL fileURLWithPath:modelPath];
NSManagedObjectModel * oldManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSSet *vIdentifiers = [oldManagedObjectModel versionIdentifiers];
for (NSString * identifier in vIdentifiers) {
NSLog(@"Old Model : %@",identifier);
}
return [oldManagedObjectModel autorelease];
}
I know these are just snippets of code, but I really hope it helps you solve your problem, if you need anything else just ask.
Your NSEntityMigrationPolicy is not being called because you set NSInferMappingModelAutomaticallyOption to @(YES) - it should be @(NO)
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