2010-10-22 3 views
0

Je suis un peu confus sur la bonne façon de faire en sorte que ma classe soutienne la mécanique NSCopy et j'espère que quelqu'un pourra m'aider à résoudre les problèmes. La grande question est la suivante: Si ma classe est principalement immuable sauf pour une propriété de collections, lorsque j'implémente la méthode 'copyWithZone' via l'héritage NSCopy, dois-je faire la version où je retourne un moi qui avait un retain appelé comme ceci:Implémentation de NSCopy

- (id)copyWithZone:(NSZone *)zone 
{ 
    return [self retain]; 
} 

ou dois-je faire d'autre version qui prend pour tenir compte des politiques utilisées par NSCopyObject comme indiqué dans le guide de programmation de gestion de la mémoire publié par Apple? (J'ai lu un certain nombre de messages sur la façon dont NSCopyObject est dangereux, donc il faut être prudent avec leurs implémentations).

- (id)copyWithZone:(NSZone *)zone 
{ 
    NSCell *cellCopy = NSCopyObject(self, 0, zone); 
    /* Assume that other initialization takes place here. */ 
    cellCopy->image = nil; 
    [cellCopy setImage:[self image]]; 
    return cellCopy; 
} 

Ma classe a ivars sont un mélange de types primitifs, de types d'objets et d'une collection NSArray. Je souhaite que la classe soit semi-immuable dans le sens où les clients ne peuvent modifier aucune des propriétés intrinsèques après la création initiale de la classe, mais à un moment donné, le client recevra des données connexes supplémentaires qui doivent être ajoutées à la classe. De plus, lorsque les clients conservent une instance, ils doivent avoir leur propre copie au lieu de la partager, c'est donc une copie en profondeur plutôt qu'une copie superficielle.

Le code:

@interface MySampleClass : NSObject { 
NSString *myName; 
NSString *myTitle; 
BOOL  isAFlag; 

NSArray *aListOfProperites; // collection holds objects of another class named 'MySampleProperty' 
} 

@property (nonatomic, copy, readonly) NSString *myName; 
@property (nonatomic, copy, readonly) NSString *myTitle; 
@property (nonatomic, readonly) BOOL isAFlag; 

@property (nonatomic, copy, readonly) NSArray *aListOfProperties; 

-(id)initWithNameTitleAndFlag:(NSString *)aName title:(NSString *)aTitle flag:(BOOL)aFlag; 

-(void)addProperty:(MySampleProperty *)aProperty; 
@end 

@implementation MySampleClass 

-(id)initWithNameTitleAndFlag:(NSString *)aName title:(NSString *)aTitle flag:(BOOL)aFlag 
{ 
    self = [super init]; 
    if (nil != self) 
    { 
     [self setMyName:aName]; 
     [self setMyTitle:aTitle]; 
     [self setAFlag:aFlag]; 
    } 
    return self; 
} 

// all of my object setters do a 'copy' instead of retain or assign 
-(void)setMyName:(NSString *)aNewName 
{ 
if (aNewName != myName) 
{ 
    [myName release]; 
    myName = [aNewName copy]; 
} 
} 
- (id)copyWithZone:(NSZone *)zone 
{ 
// do I do a simple retain on the object or follow NSCopyObject policies? 
} 

@end 

Répondre

1

Si votre classe était totalement immuable, je suggère une copie superficielle. Cependant, parce que ce n'est pas le cas, vous devrez faire une copie profonde afin d'éviter les bogues (si quelque chose fait une copie superficielle de votre classe, s'attendre à une copie profonde, puis la modifie, l'objet original changera aussi, quand cela ne semble pas devoir). Faites une copie profonde.

+0

Faire une copie en profondeur est logique. Alors, quelle est la bonne façon d'implémenter 'copyWithZone'? –

+0

Vous pouvez le faire comme ceci: http://pastie.org/1241957 (ce code n'a pas été testé, mais il devrait fonctionner - exécuter des tests par vous-même pour confirmer). –

+2

Abel, si ma réponse a suffisamment répondu à ta question, n'oublie pas de la marquer comme la réponse! Merci... ;) –