2

I'm migrating a Data Model using a Mapping Model.

An entity has an attribute named deleted that is not migrating because Core Data takes the deleted property of the NSManagedObject instead of mine.

How can I force the Mapping Model to use my attribute?

Is there anything I can use in the Value Expression? This is what I use now:

enter image description here

Thank you.

Matt39
  • 149
  • 8
  • I would try `isDeleted` or `getDeleted` - though I fear they will have the same problem (if they work at all). – pbasdf Apr 29 '16 at 11:28
  • See here: http://stackoverflow.com/a/16003894/826716 and here: http://stackoverflow.com/a/4718806/826716 . I'm afraid it's not possible with lightweight migration. Maybe it's worth trying `NSMigrationManager`: https://www.objc.io/issues/4-core-data/core-data-migration/ . – bteapot Apr 29 '16 at 12:53
  • I wouldn't even go down the route of heavy migration, do a lightweight migration and then data processing after the migration. – Marcus S. Zarra Apr 29 '16 at 16:13

2 Answers2

1

Unfortunately you used a reserved word (which I suspect produced a warning at the time).

Your best bet is to do a lightweight migration and that value will NOT migrate. Then after the migration; iterate over the data and update the value manually per object. You will only need to do this once as once the migration is complete that old reserved word property will be gone.

Marcus S. Zarra
  • 46,571
  • 9
  • 101
  • 182
  • Thanks, but how can I update that attribute if I've lost the value during the lightweight migration? – Matt39 Apr 29 '16 at 16:59
  • You create a new attribute without removing the old one then migrate. After the migration, iterate over the objects and set the new value from the old value. At some future point you can remove the old, now unused value. – Marcus S. Zarra Apr 29 '16 at 18:13
1

I've found the solution:

I implemented a custom MigrationPolicy as follow:

- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sourceInstance
                                  entityMapping:(NSEntityMapping *)mapping
                                        manager:(NSMigrationManager *)manager
                                          error:(NSError *__autoreleasing *)error
{
    NSManagedObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:[mapping destinationEntityName] inManagedObjectContext:[manager destinationContext]];

    // Add the old 'deleted' attribute to a renamed attribute
    [newObject setValue:[NSNumber numberWithBool:[((OldEntityModel *)sourceInstance) deleted]] forKey:@"newDeletedAttribute"];

    // Add all the other attributes
    [newObject setValue:[sourceInstance valueForKey:@"field1"] forKey:@"field1"];
    [newObject setValue:[sourceInstance valueForKey:@"field2"] forKey:@"field2"];

    // Add the relationships
    NSSet *relationshipAttribute = [[NSSet alloc] initWithArray:[manager destinationInstancesForEntityMappingNamed:@"OtherEntityToOtherEntity" sourceInstances:@[[sourceInstance valueForKey:@"relationshipAttribute"]]]];
    [newObject relationshipAttribute forKey:@"relationshipAttribute"];

    [manager associateSourceInstance:sourceInstance withDestinationInstance:newObject forEntityMapping:mapping];

    return YES;
}

Casting the sourceEntity to the old model version permits to access the deleted attributed that was unaccessible in lightweight migrations or mapping models.

Matt39
  • 149
  • 8