How can I duplicate, or copy a Core Data Managed Object?

37,326

Solution 1

Here's a class I created to perform a "deep copy" of managed objects: attributes and relationships. Note that this does not check against loops in the object graph. (Thanks Jaanus for the starting off point...)

@interface ManagedObjectCloner : NSObject {
}
+(NSManagedObject *)clone:(NSManagedObject *)source inContext:(NSManagedObjectContext *)context;
@end

@implementation ManagedObjectCloner

+(NSManagedObject *) clone:(NSManagedObject *)source inContext:(NSManagedObjectContext *)context{
    NSString *entityName = [[source entity] name];

    //create new object in data store
    NSManagedObject *cloned = [NSEntityDescription
                               insertNewObjectForEntityForName:entityName
                               inManagedObjectContext:context];

    //loop through all attributes and assign then to the clone
    NSDictionary *attributes = [[NSEntityDescription
                                 entityForName:entityName
                                 inManagedObjectContext:context] attributesByName];

    for (NSString *attr in attributes) {
        [cloned setValue:[source valueForKey:attr] forKey:attr];
    }

    //Loop through all relationships, and clone them.
    NSDictionary *relationships = [[NSEntityDescription
                                   entityForName:entityName
                                   inManagedObjectContext:context] relationshipsByName];
    for (NSRelationshipDescription *rel in relationships){
        NSString *keyName = [NSString stringWithFormat:@"%@",rel];
        //get a set of all objects in the relationship
        NSMutableSet *sourceSet = [source mutableSetValueForKey:keyName];
        NSMutableSet *clonedSet = [cloned mutableSetValueForKey:keyName];
        NSEnumerator *e = [sourceSet objectEnumerator];
        NSManagedObject *relatedObject;
        while ( relatedObject = [e nextObject]){
            //Clone it, and add clone to set
            NSManagedObject *clonedRelatedObject = [ManagedObjectCloner clone:relatedObject 
                                                          inContext:context];
            [clonedSet addObject:clonedRelatedObject];
        }

    }

    return cloned;
}


@end

Solution 2

These answers got me really close, though they did seem to have some shortcomings:

1st, I took the advice of Z S and made it a category on NSManagedObject, this seemed a little cleaner to me.

2nd, My object graph contains to-one relationships, so I started from levous's example, but note that levous's example isn't cloning the object in the case of the to-one relationship. This will cause a crash (attempting to save a NSMO from one context in a different context). I have addressed that in the example below.

3rd, I provided a cache of already-cloned objects, this prevents objects from being cloned twice and therefore duplicated in the new object graph, and also prevents cycles.

4th, I've added a black-list (list of Entity-types not to clone). I did this in part to solve one shortcoming of my final solution, which I will describe below.

NOTE: if you use what I understand to a be CoreData best-practice, always providing inverse relationships, then this will likely clone all objects that have a relationship to the object you want to clone. If you are using inverses and you have a single root object that knows about all other objects, then you will likely clone the whole thing. My solution to this was to add the blacklist and pass in the Entity type that I knew was a parent of one of the objects I wanted cloned. This appears to work for me. :)

Happy cloning!

// NSManagedObject+Clone.h
#import <CoreData/CoreData.h>

@interface NSManagedObject (Clone)
- (NSManagedObject *)cloneInContext:(NSManagedObjectContext *)context exludeEntities:(NSArray *)namesOfEntitiesToExclude;
@end


// NSManagedObject+Clone.m
#import "NSManagedObject+Clone.h"

@implementation NSManagedObject (Clone)

- (NSManagedObject *)cloneInContext:(NSManagedObjectContext *)context withCopiedCache:(NSMutableDictionary *)alreadyCopied exludeEntities:(NSArray *)namesOfEntitiesToExclude {
  NSString *entityName = [[self entity] name];

  if ([namesOfEntitiesToExclude containsObject:entityName]) {
    return nil;
  }

  NSManagedObject *cloned = [alreadyCopied objectForKey:[self objectID]];
  if (cloned != nil) {
    return cloned;
  }

  //create new object in data store
  cloned = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
  [alreadyCopied setObject:cloned forKey:[self objectID]];

  //loop through all attributes and assign then to the clone
  NSDictionary *attributes = [[NSEntityDescription entityForName:entityName inManagedObjectContext:context] attributesByName];

  for (NSString *attr in attributes) {
    [cloned setValue:[self valueForKey:attr] forKey:attr];
  }

  //Loop through all relationships, and clone them.
  NSDictionary *relationships = [[NSEntityDescription entityForName:entityName inManagedObjectContext:context] relationshipsByName];
  for (NSString *relName in [relationships allKeys]){
    NSRelationshipDescription *rel = [relationships objectForKey:relName];

    NSString *keyName = rel.name;
    if ([rel isToMany]) {
      //get a set of all objects in the relationship
      NSMutableSet *sourceSet = [self mutableSetValueForKey:keyName];
      NSMutableSet *clonedSet = [cloned mutableSetValueForKey:keyName];
      NSEnumerator *e = [sourceSet objectEnumerator];
      NSManagedObject *relatedObject;
      while ( relatedObject = [e nextObject]){
        //Clone it, and add clone to set
        NSManagedObject *clonedRelatedObject = [relatedObject cloneInContext:context withCopiedCache:alreadyCopied exludeEntities:namesOfEntitiesToExclude];
        [clonedSet addObject:clonedRelatedObject];
      }
    }else {
      NSManagedObject *relatedObject = [self valueForKey:keyName];
      if (relatedObject != nil) {
        NSManagedObject *clonedRelatedObject = [relatedObject cloneInContext:context withCopiedCache:alreadyCopied exludeEntities:namesOfEntitiesToExclude];
        [cloned setValue:clonedRelatedObject forKey:keyName];
      }
    }
  }

  return cloned;
}

- (NSManagedObject *)cloneInContext:(NSManagedObjectContext *)context exludeEntities:(NSArray *)namesOfEntitiesToExclude {
  return [self cloneInContext:context withCopiedCache:[NSMutableDictionary dictionary] exludeEntities:namesOfEntitiesToExclude];
}

@end

Solution 3

I've updated user353759's answer to support toOne relationships.

@interface ManagedObjectCloner : NSObject {
}
+(NSManagedObject *)clone:(NSManagedObject *)source inContext:(NSManagedObjectContext *)context;
@end

@implementation ManagedObjectCloner

+(NSManagedObject *) clone:(NSManagedObject *)source inContext:(NSManagedObjectContext *)context{
    NSString *entityName = [[source entity] name];

    //create new object in data store
    NSManagedObject *cloned = [NSEntityDescription
                               insertNewObjectForEntityForName:entityName
                               inManagedObjectContext:context];

    //loop through all attributes and assign then to the clone
    NSDictionary *attributes = [[NSEntityDescription
                                 entityForName:entityName
                                 inManagedObjectContext:context] attributesByName];

    for (NSString *attr in attributes) {
        [cloned setValue:[source valueForKey:attr] forKey:attr];
    }

    //Loop through all relationships, and clone them.
    NSDictionary *relationships = [[NSEntityDescription
                                    entityForName:entityName
                                    inManagedObjectContext:context] relationshipsByName];
    for (NSString *relName in [relationships allKeys]){
        NSRelationshipDescription *rel = [relationships objectForKey:relName];

        NSString *keyName = [NSString stringWithFormat:@"%@",rel];
        if ([rel isToMany]) {
            //get a set of all objects in the relationship
            NSMutableSet *sourceSet = [source mutableSetValueForKey:keyName];
            NSMutableSet *clonedSet = [cloned mutableSetValueForKey:keyName];
            NSEnumerator *e = [sourceSet objectEnumerator];
            NSManagedObject *relatedObject;
            while ( relatedObject = [e nextObject]){
                //Clone it, and add clone to set
                NSManagedObject *clonedRelatedObject = [ManagedObjectCloner clone:relatedObject 
                                                                        inContext:context];
                [clonedSet addObject:clonedRelatedObject];
            }
        }else {
            [cloned setValue:[source valueForKey:keyName] forKey:keyName];
        }

    }

    return cloned;
}

Solution 4

This is @Derricks answer, modified to support the new-as-of iOS 6.0 ordered to-many relationships by interrogating the relationship to see if it is ordered. While I was there, I added a simpler -clone method for the common case of cloning within the same NSManagedObjectContext.

//
//  NSManagedObject+Clone.h
//  Tone Poet
//
//  Created by Mason Kramer on 5/31/13.
//  Copyright (c) 2013 Mason Kramer. The contents of this file are available for use by anyone, for any purpose whatsoever.
//

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface NSManagedObject (Clone) {
}

-(NSManagedObject *)cloneInContext:(NSManagedObjectContext *)context withCopiedCache:(NSMutableDictionary *)alreadyCopied exludeEntities:(NSArray *)namesOfEntitiesToExclude;
-(NSManagedObject *)cloneInContext:(NSManagedObjectContext *)context exludeEntities:(NSArray *)namesOfEntitiesToExclude;
-(NSManagedObject *) clone;

@end

//
//  NSManagedObject+Clone.m
//  Tone Poet
//
//  Created by Mason Kramer on 5/31/13.
//  Copyright (c) 2013 Mason Kramer. The contents of this file are available for use by anyone, for any purpose whatsoever.
//


#import "NSManagedObject+Clone.h"

@implementation NSManagedObject (Clone)

-(NSManagedObject *) clone {
    return [self cloneInContext:[self managedObjectContext] exludeEntities:@[]];
}

- (NSManagedObject *)cloneInContext:(NSManagedObjectContext *)context withCopiedCache:(NSMutableDictionary *)alreadyCopied exludeEntities:(NSArray *)namesOfEntitiesToExclude {
    NSString *entityName = [[self entity] name];

    if ([namesOfEntitiesToExclude containsObject:entityName]) {
        return nil;
    }

    NSManagedObject *cloned = [alreadyCopied objectForKey:[self objectID]];
    if (cloned != nil) {
        return cloned;
    }

    //create new object in data store
    cloned = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
    [alreadyCopied setObject:cloned forKey:[self objectID]];

    //loop through all attributes and assign then to the clone
    NSDictionary *attributes = [[NSEntityDescription entityForName:entityName inManagedObjectContext:context] attributesByName];

    for (NSString *attr in attributes) {
        [cloned setValue:[self valueForKey:attr] forKey:attr];
    }

    //Loop through all relationships, and clone them.
    NSDictionary *relationships = [[NSEntityDescription entityForName:entityName inManagedObjectContext:context] relationshipsByName];
    for (NSString *relName in [relationships allKeys]){
        NSRelationshipDescription *rel = [relationships objectForKey:relName];

        NSString *keyName = rel.name;
        if ([rel isToMany]) {
            if ([rel isOrdered]) {
                NSMutableOrderedSet *sourceSet = [self mutableOrderedSetValueForKey:keyName];
                NSMutableOrderedSet *clonedSet = [cloned mutableOrderedSetValueForKey:keyName];

                NSEnumerator *e = [sourceSet objectEnumerator];

                NSManagedObject *relatedObject;
                while ( relatedObject = [e nextObject]){
                    //Clone it, and add clone to set
                    NSManagedObject *clonedRelatedObject = [relatedObject cloneInContext:context withCopiedCache:alreadyCopied exludeEntities:namesOfEntitiesToExclude];


                    [clonedSet addObject:clonedRelatedObject];
                    [clonedSet addObject:clonedRelatedObject];
                }
            }
            else {
                NSMutableSet *sourceSet = [self mutableSetValueForKey:keyName];
                NSMutableSet *clonedSet = [cloned mutableSetValueForKey:keyName];
                NSEnumerator *e = [sourceSet objectEnumerator];
                NSManagedObject *relatedObject;
                while ( relatedObject = [e nextObject]){
                    //Clone it, and add clone to set
                    NSManagedObject *clonedRelatedObject = [relatedObject cloneInContext:context withCopiedCache:alreadyCopied exludeEntities:namesOfEntitiesToExclude];

                    [clonedSet addObject:clonedRelatedObject];
                }
            }
        }
        else {
            NSManagedObject *relatedObject = [self valueForKey:keyName];
            if (relatedObject != nil) {
                NSManagedObject *clonedRelatedObject = [relatedObject cloneInContext:context withCopiedCache:alreadyCopied exludeEntities:namesOfEntitiesToExclude];
                [cloned setValue:clonedRelatedObject forKey:keyName];
            }
        }

    }

    return cloned;
}

-(NSManagedObject *)cloneInContext:(NSManagedObjectContext *)context exludeEntities:(NSArray *)namesOfEntitiesToExclude {
    return [self cloneInContext:context withCopiedCache:[NSMutableDictionary dictionary] exludeEntities:namesOfEntitiesToExclude];
}
@end

Solution 5

Swift 5

This builds upon @Derrick & @Dmitry Makarenko & @masonk's contributions, bringing everything together, improving on it and turning it into a solution fit for 2020.

  • Handles both 1-to-1 & 1-to-Many realtionships
  • Handles ordered relationships
  • Copies the entire NSManagedObject graph (using an alreadyCopied cache)
  • Implemented as an extension to NSManagedObject

.

import CoreData

extension NSManagedObject {

    func copyEntireObjectGraph(context: NSManagedObjectContext) -> NSManagedObject {

        var cache = Dictionary<NSManagedObjectID, NSManagedObject>()
        return cloneObject(context: context, cache: &cache)

    }

    func cloneObject(context: NSManagedObjectContext, cache alreadyCopied: inout Dictionary<NSManagedObjectID, NSManagedObject>) -> NSManagedObject {

        guard let entityName = self.entity.name else {
            fatalError("source.entity.name == nil")
        }

        if let storedCopy = alreadyCopied[self.objectID] {
            return storedCopy
        }

        let cloned = NSEntityDescription.insertNewObject(forEntityName: entityName, into: context)
    alreadyCopied[self.objectID] = cloned

        if let attributes = NSEntityDescription.entity(forEntityName: entityName, in: context)?.attributesByName {

            for key in attributes.keys {
                cloned.setValue(self.value(forKey: key), forKey: key)
            }

        }

        if let relationships = NSEntityDescription.entity(forEntityName: entityName, in: context)?.relationshipsByName {

            for (key, value) in relationships {

                if value.isToMany {

                    if let sourceSet = self.value(forKey: key) as? NSMutableOrderedSet {

                        guard let clonedSet = cloned.value(forKey: key) as? NSMutableOrderedSet else {
                            fatalError("Could not cast relationship \(key) to an NSMutableOrderedSet")
                        }

                        let enumerator = sourceSet.objectEnumerator()

                        var nextObject = enumerator.nextObject() as? NSManagedObject

                        while let relatedObject = nextObject {

                            let clonedRelatedObject = relatedObject.cloneObject(context: context, cache: &alreadyCopied)
                            clonedSet.add(clonedRelatedObject)
                            nextObject = enumerator.nextObject() as? NSManagedObject

                        }

                    } else if let sourceSet = self.value(forKey: key) as? NSMutableSet {

                        guard let clonedSet = cloned.value(forKey: key) as? NSMutableSet else {
                            fatalError("Could not cast relationship \(key) to an NSMutableSet")
                        }

                        let enumerator = sourceSet.objectEnumerator()

                        var nextObject = enumerator.nextObject() as? NSManagedObject

                        while let relatedObject = nextObject {

                            let clonedRelatedObject = relatedObject.cloneObject(context: context, cache: &alreadyCopied)
                            clonedSet.add(clonedRelatedObject)
                            nextObject = enumerator.nextObject() as? NSManagedObject

                        }

                    }

                } else {

                    if let relatedObject = self.value(forKey: key) as? NSManagedObject {

                        let clonedRelatedObject = relatedObject.cloneObject(context: context, cache: &alreadyCopied)
                        cloned.setValue(clonedRelatedObject, forKey: key)

                    }

                }

            }

        }

        return cloned

    }

}

Usage:

let myManagedObjectCopy = myManagedObject.copyEntireObjectGraph(context: myContext)
Share:
37,326
Mani
Author by

Mani

Updated on April 07, 2021

Comments

  • Mani
    Mani about 3 years

    I have a managed object ("A") that contains various attributes and types of relationships, and its relationships also have their own attributes & relationships. What I would like to do is to "copy" or "duplicate" the entire object graph rooted at object "A", and thus creating a new object "B" that is very similar to "A".

    To be more specific, none of the relationships contained by "B" (or its children) should point to objects related to "A". There should be an entirely new object graph with similar relationships intact, and all objects having the same attributes, but of course different id's.

    There is the obvious manual way to do this, but I was hoping to learn of a simpler means of doing so which was not totally apparent from the Core Data documentation.

    TIA!

  • Barry Wark
    Barry Wark about 14 years
    Yes. "...surprisingly expensive..." as in unbounded memory usage. There's no way for the library to do this automatically without letting you easily shoot yourself in the foot.
  • Barry Wark
    Barry Wark about 14 years
    This doesn't do a "deep copy" of relationships that the OP wants.
  • Jaanus
    Jaanus about 14 years
    Yep, this only copies attributes. Could also do propertiesByName and/or relationshipsByName, but I won't add them to my example because (unlike the above) I have not done this kind of relation copying myself and can't vouch for it.
  • Joe D'Andrea
    Joe D'Andrea almost 14 years
    This is terrific! My only snag: UITableView does not always animate in the (effectively new) cell properly. I wonder if it concerns insertNewObjectForEntityForName:inManagedObjectContext:, THEN performing a deep copy, which may instigate more NSFetchedResultsControllerDelegate messages (?). I don't have any loops, and the data I'm copying isn't very deep per se, so hopefully that's good. Perhaps there's some way for me to somehow "build up" the entire cloned object, and THEN insert it in one fell swoop, or at least defer notification that an add took place. Looking to see if that's doable.
  • levous
    levous about 13 years
    this is fantastic! One note, however. The line 'for (NSRelationshipDescription *rel in relationships)' is not correct. relationships is an NSDictionary. I've modified to grab the NSRelationshipDescription 'for (NSString *relName in [relationships allKeys]){ NSRelationshipDescription *rel = [relationships objectForKey:relName]; ' and to check for "isToMany"
  • Mustafa
    Mustafa about 13 years
    I'm getting this error. Any pointers? *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x7003f80> was mutated while being enumerated.<CFBasicHash 0x7003f80 [0x1314400]>
  • Mustafa
    Mustafa about 13 years
    Note: I have a multi-level complex graph with one-to-one and one-to-many relationships. I've applied the fix suggested by levous for one-to-one relationships, and it seems to be working, but overall the routine is failing.
  • Z S
    Z S almost 13 years
    One small improvement might be to make it a category on NSManagedObject, so you don't have to pass in the context and the source object.
  • Nathan Gaskin
    Nathan Gaskin over 12 years
    @Mustafa I know it was months ago now, but I was having the same problem with the mutated set. Check my answer for a possible solution.
  • Duane Fields
    Duane Fields almost 12 years
    This doesn't seem to actually preserve the order of the relationships correctly. I'll let you know if I find a fix. It seems like the order ends up backwards, but it just may be indeterminate.
  • Dmitry Makarenko
    Dmitry Makarenko almost 12 years
    Are you sure? It worked for me and also I cannot locate a problem in code fragment I put as answer.
  • Duane Fields
    Duane Fields almost 12 years
    Yea, the order is indeterminate. I have a "Page" with an ordered relationship of "strokes". When I clone the page I get all the stroke relationships, but they are out of order.
  • RyeMAC3
    RyeMAC3 over 11 years
    So if I have ObjectA and ObjectB, I can copy all the entries in ObjectA and paste them into ObjectB? Then delete ObjectA and have just ObjectB with all my entries? Is that the purpose of a "deep copy"? Because that's what I'm looking for.
  • Felix Lamouroux
    Felix Lamouroux over 11 years
    [cloned setValue:[source valueForKey:relName] forKey:relName]; does not clone the target object in the to-one-relation and leads to an exception, because you might try to link objects from different contexts. It is also inconsistent with the toMany branch. It is probably a typo/minor oversight.
  • Christoph
    Christoph over 11 years
    NSString *keyName = [NSString stringWithFormat:@"%@",rel] does not contain the relationships name in iOS6, use [NSString stringWithFormat:@"%@",rel.name]. Otherwise keyName contains the whole description string for the relation
  • Jeff
    Jeff about 11 years
    This worked like a charm for me. I had both to-many and to-one relationships. I had objects in the hierarchy I did not want cloned. My tests indicate it worked fine. I owe you a beer. FYI, I did convert back to class method from category for app architecture reasons. I also swapped copiedCache argument with excludeEntities to follow Apple naming guidelines of ever lengthening method names. And fixed your "exlude" misspelling.
  • Alex Stone
    Alex Stone about 11 years
    Does not work for my RestKit project in iOS6 with ARC. I get EXC_BAD_ACCESS at NSEnumerator *e = [sourceSet objectEnumerator];
  • Alex Stone
    Alex Stone about 11 years
    This code works in iOS6 with ARC for nested relationship and using RestKit! Thanks
  • masonk
    masonk almost 11 years
    This is the one that was closest to working. However, some of my relationships are defined as "ordered", something new to iOS 6. So I am posting my modification that checks that.
  • Diego Barros
    Diego Barros almost 11 years
    This is the most complete implementation here.
  • Joe
    Joe over 10 years
    This is the best solution but there is one bug. You need to check if clonedRelatedObject is nil before adding it to clonedSet. If the related object was part of namesOfEntitiesToExclude it will be nil and throw an error when trying to add it to clonedSet.
  • Mark Bridges
    Mark Bridges over 10 years
    I've tried this but get this error this line. NSMutableSet *clonedSet = [cloned mutableSetValueForKey:keyName]; *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'NSManagedObjects of entity 'Form' do not support -mutableSetValueForKey: for the property 'contains''
  • Mark Bridges
    Mark Bridges over 10 years
    Had a crash trying to use Derrick's answer but this one works for me.
  • MGM
    MGM about 10 years
    There are lots of different answers here, but this one worked with objects that had attributes that were both toone and tomany.
  • Aqib Mumtaz
    Aqib Mumtaz over 9 years
    This is great answer, must be promoted!
  • elsurudo
    elsurudo almost 9 years
    This generally works, except in my case, the ordering of ordered relationships is reversed every time I copy! Any ideas? Also, is there a reason you do [clonedSet addObject:clonedRelatedObject]; twice for ordered relationships?
  • elsurudo
    elsurudo almost 9 years
    I always get a reverse ordering. Have you found a fix, perchance?
  • Damien Romito
    Damien Romito over 8 years
    Yes, exluding entities didn't work with MasonK's version! Thanks Justin
  • Benjohn
    Benjohn over 8 years
    I think that the ordering here doesn't work well. It seems to have a bug that I fixed in my own variant. For ordered relationships that have an inverse, depth first cloning (as used in all these implementations) can recursively cause the other end of the relationship to be set, which updates the ordered set as you build it. The work around for this is to build the complete ordered set and then assign using the primitive KVO variant.
  • anoop4real
    anoop4real about 8 years
    @MarkBridges I know its late but anyways, I got this error because I had an ordered relation so I used solution by Dmitry Makarenko where ordered relation is also handled and it worked.
  • Aviram Netanel
    Aviram Netanel about 8 years
    it worked! but when I change the source to nil, the clone is also changing! how is that possible?!?!
  • koen
    koen about 8 years
    @elsurudo: I think that is a typo.
  • kelin
    kelin about 7 years
    What is properties and attributes? How do you get them?
  • Roberto Frontado
    Roberto Frontado about 7 years
    Bad typo then ;)
  • Bisca
    Bisca about 7 years
    copyRelations Bool is used to avoid copying inverse relations in our object
  • Zia
    Zia almost 7 years
    How come you are calling this a shallow copy?
  • Bisca
    Bisca almost 7 years
    What name do you propose? I called shallow because It isn't a complete copy. In the case the relationed entities has another relation (not only the bidirectional one) then, they won't be copied. That method works for some cases but you can modify it to your needs
  • Zia
    Zia almost 7 years
    Ah that makes sense. Perfect name.
  • Yoon Lee
    Yoon Lee over 6 years
    This also no copies but references exist values to the attributes. Simply, ObjA's value being pointed to ObjB, meaning if value being modified affect ObjA.
  • Motti Shneor
    Motti Shneor over 6 years
    This answer is great, and fits exactly MY needs, but is not answering to the original question - which was about duplicating a whole "tree" of inter-related NSManagedObject. I think other answers got it wrong too (because of back relations and other circular relations, and the possibility of "meeting" the same entity again and again via indirect relations - I do believe the OP didn't mean to make a duplicate of these evert time...
  • Motti Shneor
    Motti Shneor over 6 years
    Pay attention - in some place you have duplicate code line : [clonedSet addObject:clonedRelatedObject]; It may not have effect since clonedSet is an NSSet - still its not desirable.
  • Aaban Tariq Murtaza
    Aaban Tariq Murtaza almost 6 years
    question was not relevant to shallow copy.
  • Aaban Tariq Murtaza
    Aaban Tariq Murtaza almost 6 years
    who asked for shallow copy?
  • Rillieux
    Rillieux over 3 years
    Could you clarify something - does this "clone" automatically get added to the database, or is it in "limbo" until is the context is saved?
  • ngb
    ngb over 2 years
    there is no managedObject.save() in the code, so u have to save it yourself. how he's done it is the right way to do it.
  • ReDetection
    ReDetection over 2 years
    excuse me, what about thread safety? I have a pretty large database and I don't want to block the main thread, but contexts are tied to their own queue nowadays