Core Data Migration: Attribute Mapping Value Expression
Asked Answered
R

1

7

I currently have a cardType attribute on my entity, which in the old model could be "Math", "Image" or "Text". In the new model, I'll be using just "Math" and "Text" and also have a hasImage attribute, which I want to set to true if the old cardType was Image (which I want to change to "Text").

Lastly, I have a set of another entity, "card", of which a set can be associated with a deck, and in each of those, I'll also have hasImage which I want to set to true if the deck was of "Image" type before.

Is this all possible using the Value Expression in the Mapping Model I've created between the two versions, or will I have to do something else?

I can't find any document telling me exactly what is possible in the Value Expression (Apple's doc - http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CoreDataVersioning/Articles/vmMappingOverview.html%23//apple_ref/doc/uid/TP40004735-SW3 - only has a very simple transformation). If I have to do something else, what would that be? This seems simple enough that an expression should be able to do it.

Redbreast answered 20/3, 2011 at 3:28 Comment(0)
B
27

One thing you can do is create a custom migration policy class that has a function mapping your attribute from the original value to a new value. For example I had a case where I needed to map an entity called MyItems that had a direct relationship to a set of values entities called "Items" to instead store an itemID so I could split the model across multiple stores.

The old model looked like this: old model

The new model looks like this: new model

To do this, I wrote a mapping class with a function called itemIDForItemName and it was defined as such:

@interface Migration_Policy_v1tov2 : NSEntityMigrationPolicy {

  NSMutableDictionary *namesToIDs;
}

- (NSNumber *) itemIDForItemName:(NSString *)name;
@end

#import "Migration_Policy_v1tov2.h"

@implementation Migration_Policy_v1tov2


    - (BOOL)beginEntityMapping:(NSEntityMapping *)mapping manager:(NSMigrationManager *)manager error:(NSError **)error {
        
        namesToIDs = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1],@"Apples",
                      [NSNumber numberWithInt:2],@"Bananas",
                      [NSNumber numberWithInt:3],@"Peaches",
                      [NSNumber numberWithInt:4],@"Pears",
                      [NSNumber numberWithInt:5],@"Beef",
                      [NSNumber numberWithInt:6],@"Chicken",
                      [NSNumber numberWithInt:7],@"Fish",
                      [NSNumber numberWithInt:8],@"Asparagus",
                      [NSNumber numberWithInt:9],@"Potato",
                      [NSNumber numberWithInt:10],@"Carrot",nil];
        return YES;
    }
    - (NSNumber *) itemIDForItemName:(NSString *)name {
        
        NSNumber *iD = [namesToIDs objectForKey:name];
        
        NSAssert(iD != nil,@"Error finding ID for item name:%@",name);
        
        return iD;
    }
    @end

Then for the related Mapping Name for the attribute in your mapping model you specify the Value Expression as the result of your function call as such: FUNCTION($entityPolicy,"itemIDForItemName:",$source.name) **

You also have to set the Custom Policy Field of your Mapping Name for that attribute to your mapping class name (in this case Migration_Policy_v1tov2).

**note this should match the selector signature of the method

Mapping Model

Boron answered 22/3, 2011 at 0:41 Comment(4)
This is what I ended up doingRedbreast
Thank you for this answer! Your brief example saved me a lot of time and frustration. (Would it kill Apple to include stuff like this in their documentation once in a while?)Invertebrate
@gregc First of all, thanks for the interesting approach I didn't find elsewhere. It's just what I needed. But unfortunately, I can't get it work. It seems the methods in my custom migration policy class aren't called. In the resulting DB the fields that should be filled with values returned by these methods are empty. And also, I set breakpoints in these methods which are not triggered. What could be done wrong? Do you know any way of debugging the migration process (or at least to ensure it's performed)? Thank you!Junette
has this view changed in xcode 4.62 ? I can't seem to find these forms where you can enter the custom policyFactor

© 2022 - 2024 — McMap. All rights reserved.