-->

core data manual migration

2019-04-13 10:02发布

问题:

I'm trying to migrate to a new completely different model in my project. The changes are way too much for a lightweight migration and I think the best way is to iterate through the top level objects and set all the attributes and relationships myself.

How can I set up the migration process to be completely manual like this. I've looked into NSMigrationManager which seems to require an NSMappingModel. The only examples and tutorials I've seen use inferredMappingModelForSourceModel:destinationModel:error: which I can't use because it isn't able to infer the mapping model.

Am I on the right path and if so how can I create a mapping model completely manually in code? Thanks for the help.

回答1:

If your model changes are such that you at least have an source and destination entity level mapping (For example you had a Vehicle entity in your old model and now you want to migrate that data to Car) then you can use a custom mapping model with a migration policy.

The process is fairly straightforward, in Xcode, try to add a new mapping model file to your project, select the source model version and destination model version. Xcode tries to be smart about figuring out the mapping between attributes of your source and destination entities. If it isn't able to, it'll just leave the mappings blank and you can set your own mapping.

If you'd like to do something other than simple assignment or blanking out or setting a default value for attributes during mapping, use something called an NSEntityMigrationPolicy. Create your own subclass and implement this method to do your custom mapping:

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)instance
                                      entityMapping:(NSEntityMapping *)mapping
                                            manager:(NSMigrationManager *)manager
                                              error:(NSError **)error {
    NSArray *_properties = [mapping attributeMappings];
    for (NSPropertyMapping *_property in _properties) {
        if ([[_property name] isEqualToString:@"companyName"]) {
            NSExpression *_expression = [NSExpression expressionForConstantValue:@"10to1"];
            [_property setValueExpression:_expression];
        }
    }

    return [super createDestinationInstancesForSourceInstance:instance 
                                                entityMapping:mapping 
                                                      manager:manager 
                                                        error:error];
}

You can read more about how to do a custom migration here.



回答2:

Check out CDWrangler. It's an open source Core Data controller that can handle lightweight and manual migration progressively.

After you create your mapping model, and any custom policies you need you just need to do this

// Migration
if ([[CDWrangler sharedWrangler] isMigrationNeeded]) {
    // The key is the name of your starting model, and the value is the name of your mapping model.  In this example they are Model.xcdatamodel and MappingModel.xcmappingmodel
    [CDWrangler sharedWrangler].mappingsForModels = @{@"Model": @"MappingModel"};
    [[CDWrangler sharedWrangler] migrate];
}