Core Data migration problem: “Persistent store migration failed, missing source managed object model.”

后端 未结 5 1233
耶瑟儿~
耶瑟儿~ 2020-12-16 19:36

The Background

  • A Cocoa Non Document Core Data project with two Managed Object Models.
  • Model 1 stays the same. Model 2 has changed, s
5条回答
  •  旧时难觅i
    2020-12-16 20:14

    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.

提交回复
热议问题