Ces réponses m'ont vraiment proches, même s'ils ne semblent avoir quelques lacunes:
1er, j'ai pris les conseils de S Z et en a fait une catégorie sur NSManagedObject, cela semblait un peu plus propre pour moi.
2ème, Mon objet graphique contient des relations individuelles, j'ai donc commencé à partir de levous l'exemple, mais note que levous l'exemple n'est pas le clonage de l'objet dans le cas de la relation. Cela va provoquer un plantage (en essayant de sauver un NSMO d'un contexte dans un contexte différent). J'ai abordé que dans l'exemple ci-dessous.
3ème, j'ai fourni un cache de déjà-objets clonés, ce qui empêche les objets clonés deux fois et donc dupliqué dans le nouveau graphe d'objets, et empêche également les cycles.
4ème, j'ai ajouté une liste noire (liste des entités-types pas de clone). Je l'ai fait en partie pour résoudre une lacune de ma dernière solution, que je vais décrire ci-dessous.
REMARQUE: si vous utilisez ce que je peux comprendre pour un être CoreData meilleures pratiques, toujours en fournissant inverse des relations, alors ce sera probablement clone tous les objets qui ont une relation à l'objet que vous voulez cloner. Si vous utilisez des inverses et vous avez un seul objet racine qui connaît tous les autres objets, vous allez probablement clone de l'ensemble de la chose. Ma solution à ce problème est d'ajouter à la liste noire et de passer dans le type d'Entité que je connaissais était un parent de l'un des objets que je voulais cloné. Cela semble fonctionner pour moi. :)
Heureux de clonage!
// 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