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

后端 未结 5 1221
耶瑟儿~
耶瑟儿~ 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条回答
  •  攒了一身酷
    2020-12-16 20:17

    Rather than merging all models in the bundle, I've specified the two models I want to use (model 1 and the new version of model 2) and merged them using modelByMergingModels:

    This doesn't seem right. Why merge the models? You want to use model 2, migrating your store from model 1.

    From the NSManagedObjectModel class reference

    modelByMergingModels:

    Creates a single model from an array of existing models.

    You don't need to do anything special/specific with your source model (model 1).. just so long as it's in your bundle, the automatic lightweight migration process will discover and use it.

    I would suggest abandoning the mapping model you created in Xcode, as I've seen terrible performance in comparison with the automatic-lightweight migrations. Your mileage may vary, my changes between models are different to yours, but i wouldn't be surprised. Try some timing with and without your own mapping model in the bundle.

     /* Inferred mapping */
     NSError *error;
     NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                              [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                              [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,nil];
     NSPersistentStore *migratedStore = [persistentStoreCoordinator addPersistentStoreWithType:nil
                                                                                 configuration:nil
                                                                                           URL:self.storeURL
                                                                                       options:options
                                                                                         error:&error];
     migrationWasSuccessful = (migratedStore != nil);
    

    You can verify in your code that your source model is available, by attempting to load it and verify that it is not nil:

    NSString *modelDirectoryPath = [[NSBundle mainBundle] pathForResource:@"YourModelName" ofType:@"momd"];
    if (modelDirectoryPath == nil) return nil;
    NSString *modelPath = [modelDirectoryPath stringByAppendingPathComponent:@"YourModelName"];
    NSURL *modelFileURL = [NSURL fileURLWithPath:modelPath];
    NSManagedObjectModel *modelOne = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelFileURL];
    if (modelOne == nil) {
        NSLog(@"Woops, Xcode lost my source model");
    }
    else {
        [modelOne release];
    }
    

    This assumes in your project you have a resource "YourModelName.xcdatamodeld" and "YourModelName.xcdatamodel" within it.


    Also, you can check if that model is compatible with your existing, pre-migration persistent store:

    NSError *error;
    NSDictionary *storeMeta = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:nil URL:self.storeURL error:&error];
    if (storeMeta == nil) {
        // Unable to read store meta
        return NO;
    }
    BOOL isCompatible = [modelOne isConfiguration:nil compatibleWithStoreMetadata:storeMeta];
    

    That code assumes you have a method -storeURL to specify where the persistent store is loaded from.

提交回复
热议问题