I have 2 object models in Core Data (say v1 and v2). This migration is eligible for light weight migration. Now, I want to execute custom code after the migration but only when the migration is from v1 to v2. Later on if I introduce v3, I don't want the custom code to get executed.
Is there a way to do this?
Thanks in advance, Anupam
Core Data can typically perform an automatic data migration, referred to as lightweight migration. Lightweight migration infers the migration from the differences between the source and the destination managed object models.
We perform heavyweight migration when we have either normalized or generalized our database. In such cases, lightweight migration won't help us. We will have to manually map attributes of the old data model to the new data model, and doing so is called heavyweight migration.
Migrations happen in three steps: First, Core Data copies over all the objects from one data store to the next. Next, Core Data connects and relates all the objects according to the relationship mapping. Finally, enforce any data validations in the destination model.
Here is how to handle this situation, basically by using the store's metadata, as suggested by Apple engineers at WWDC 2010:
More or less, something like

- (void)loadStoreWithMigration:(NSURL *)url {
...
store = [psc addPersistentStoreWithType: NSSQLiteStoreType configuration: nil URL: url options: opts error: &err];
m = [store metadata];
key = @”DonePostProcessing”;
if (m && ([[m objectForKey: key] integerValue] < 2) ){
[self doPostProcessingInContext: context];
m2 = [[m mutableCopy] autorelease];
[m2 setObject: [NSNumber numberWithInteger: 2] forKey: key];
[store setMetadata: m2];
ok = [context save:&err];
}
}
There might be a better way, buy this should work:
Keep track of the DB version by keeping an entity in Core Data named "Information" and have a property named "CoreDataVersion".
After the migration code finishes add code to check for the version number in the core data.
If the value of "CoreDataVersion" is "v1" and your app is now at "v2" (this can be hardcoded with each version), execute the additional custom code and then write the new version back to the DB.
If you already have "v1" published to users, just say that if there is no "CoreDataVersion" in the DB, then it is "v1".
- (void) _performMaintanaceUpdate:(NSUInteger) newVersion oldVersion:(NSUInteger) oldVersion {
if (newVersion>=1020500 && oldVersion < 1020500) {
NSString *storePath = [[PreferenceDataModel getDataPath] stringByAppendingPathComponent: @"wcal.sqlite"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:storePath]) {
[fileManager removeItemAtPath:storePath error:NULL];
}
[PreferenceDataModel setVersionOfLastMaintanace:newVersion];
}
}
(void) _checkAndPerformMaintenance{
NSString* strVersion = [PreferenceDataModel getApplicationVersion];
//legal version is xx.xx.xx where x is a dec digit 1.2 or 1.2.33 is legit
NSUInteger ver = 0;
NSUInteger finalVer = 0;
int t = 3;
for (int i=0; i<[strVersion length]; i++) {
char c = [strVersion characterAtIndex:i];
if (isdigit(c)) {
ver*=10;
ver+=c - 48;
}
else {
finalVer+= ver * pow(100, t--);
ver = 0;
}
}
finalVer+= ver * pow(100, t);
[self _performMaintanaceUpdate:finalVer oldVersion:[PreferenceDataModel getVersionOfLastMaintanace]];
}
and this is how you retrieve apps version
+(NSString *) getApplicationVersion {
return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
}
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