[CoreData] Duplicating an object

As any of you knows, duplicating an object in coredata is just a nightmare : you basically have to start afresh each and every single time for each object, then iterate over attributes and relationships.

It so happens I have to do that often in one of my projects. I have to duplicate them except for a couple of attributes and relationships, and there are 20 of each on average (I didn’t come up with the model, OK?).

So, I came up with this code. Feel free to use it, just say hi in the comments, via mail, or any other way if you do!

@implementation NSManagedObject (Duplication)
+ (BOOL) duplicateAttributeValuesFrom:(NSManagedObject*)source To:(NSManagedObject*)dest ignoringKeys:(NSArray*)ignore {
    if(source == nil || dest == nil) return NO;
    if(![[source entity] isEqual:[dest entity]]) return NO;
 
    for(NSString *attribKey in [[[source entity] attributesByName] allKeys]) {
        if([ignore containsObject:attribKey]) continue;
 
        [dest setValue:[source valueForKey:attribKey] forKey:attribKey];
    }
 
    return YES;
}
 
+ (BOOL) duplicateRelationshipsFrom:(NSManagedObject*)source To:(NSManagedObject*)dest ignoringKeys:(NSArray*)ignore {
    if(source == nil || dest == nil) return NO;
    if(![[source entity] isEqual:[dest entity]]) return NO;
 
    NSDictionary *relationships = [[source entity] relationshipsByName];
    for(NSString *attribKey in [relationships allKeys]) {
        if([ignore containsObject:attribKey]) continue;
 
        if([((NSRelationshipDescription*)[relationships objectForKey:attribKey]) isToMany]) {
            [dest setValue:[NSSet setWithSet:[source valueForKey:attribKey]] forKey:attribKey];
 
        } else {
            [dest setValue:[source valueForKey:attribKey] forKey:attribKey];
        }
 
    }
 
    return YES;
}
 
@end
  

Comments

  1. May I recommend using an NSSet * for the “ignore” argument?
    I’ve implemented about the same idea a long time ago, and copying hundreds of thousands of objects with many keys to ignore is tremendously faster with an NSSet.

  2. Yea, but if your ignore starts to get really big, what’s the point of duplicating the object anyway? :) In my exemple, I rarely have more than 3-4, which makes NSArray and NSSet comparable, in terms of performance.

Leave a Reply