The Background
While attempting to upgrade an existing app's Core Data model (and migrate legacy data), I just ran across a scenario where a third-party Framework was writing data into an app's database. I was getting this error, "Can't find model for source store." Because the third party model was not loaded when I was attempting the migration, the migration was failing.
I wrote this method (below) during troubleshooting this issue. It may be useful to those who are facing these types of issues.
- (BOOL) checkModelCompatibilityOfStoreWithURL: (NSURL *) myStoreURL
forModelNamed: (NSString *) myModelName
withBasePath: (NSString *) myBasePath;
{
NSError * error = nil;
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:myStoreURL error:&error];
if (!storeMeta) {
NSLog(@"Unable to load store metadata from URL: %@; Error = %@", myStoreURL, error);
return NO;
}
NSString * modelPath = [myBasePath stringByAppendingPathComponent: myModelName];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: modelPath]) {
// uh oh
NSLog(@"Can't find model.");
return NO;
}
NSURL * modelURL = [NSURL fileURLWithPath: modelPath];
NSManagedObjectModel * model = [[[NSManagedObjectModel alloc] initWithContentsOfURL: modelURL] autorelease];
BOOL result = [model isConfiguration: nil compatibleWithStoreMetadata: storeMeta];
NSLog(@"Tested model, %@, is%@ compatible with Database", modelPath, result ? @"" : @" ~not~");
return result;
}
This code snippet will obtain a store's metadata.
NSError *error = nil;
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:storeUrl error:&error];
NSLog(@"%@", [storeMeta objectForKey: @"NSStoreModelVersionHashes"]);
The VersionInfo.plist (stored in the compiled app's bundle) contains the hashes that are associated with the various entities in your models (base64 encoding). Similarly, a BLOB column in the datastore (Z_METADATA.Z_PLIST) contains a binary-encoded property list that has the hashes (also base64 encoded) for each entity that is associated with the data.
The -entitiesByName method on NSManagedObjectModel is useful for dumping the entities and hashes that exist within a specific model.