2010-01-06 20 views
9

¿Es correcto el copyWithZone (ver más abajo), particularmente el bit donde utilizo los setters para rellenar las variables de instancia del nuevo objeto?copyWithZone configurando variables de instancia?

@interface Planet : NSObject <NSCopying> 
{ 
    NSString *name; 
    NSString *type; 
    NSNumber *mass; 
    int index; 
} 
@property(copy) NSString *name; 
@property(copy) NSString *type; 
@property(retain) NSNumber *mass; 
@property(assign) int index; 
-(void)display; 
@end 

-(id) copyWithZone: (NSZone *) zone { 
    Planet *newPlanet = [[Planet allocWithZone:zone] init]; 
    NSLog(@"_copy: %@", [newPlanet self]); 
    [newPlanet setName:name]; 
    [newPlanet setType:type]; 
    [newPlanet setMass:mass]; 
    [newPlanet setIndex:index]; 
    return(newPlanet); 
} 

EDIT_001:

¿Es esta una manera mejor?

-(id) copyWithZone: (NSZone *) zone { 
    Planet *newPlanet = [[[self class] allocWithZone:zone] init]; 
    [newPlanet setName:[self name]]; 
    [newPlanet setType:[self type]]; 
    [newPlanet setMass:[self mass]]; 
    [newPlanet setIndex:[self index]]; 
    return(newPlanet); 
} 

muchas gracias

Gary

+0

Ambos funcionan, pero la segunda forma tiene invocaciones innecesarias de métodos. – NSResponder

+0

@NSResponder: supongo que si escribe antes de regresar (nuevoPlanet); algo como [self setMass: a_new_number], cambiará el nuevo valor dePlanet.mass, ya que se conserva. ¿No es así? – Oliver

Respuesta

3

Ya se trate de una copia no deseada o no, es para que usted decida. La razón para sintetizar los descriptores de acceso con el calificador de copia es garantizar la propiedad de esos objetos.

Tenga en cuenta, sin embargo, que los objetos inmutables como un NSNumber o un NSString en realidad no duplicarán su almacenamiento cuando se les envíe un mensaje, aumentarán sus recuentos de retención.

+0

Eso es cierto, ¿este método es la forma correcta de establecer las variables de instancia entonces o me falta una mejor manera? – fuzzygoat

3

¿Has leído this guide? Si es así, debe elegir si desea una copia superficial o profunda. Para copias superficiales, puede compartir valores: este es un enfoque típico al implementar un sublcass NSCell que comparten una instancia NSImage.

Como no conozco el contexto, diré que su implementación parece correcta.

+0

Entonces, en el ejemplo anterior, ¿se trataría de una copia profunda, ya que el colocador creará una copia, aunque aprecio que copiar un NSString en incs su conteo de retención? – fuzzygoat

6

(suponiendo que la copia en profundidad es lo que desea) para la copia que queremos hacer, use copyWithZone: para variables de instancia de objeto y simplemente establezca variables de instancia primitiva usando =.

- (id)copyWithZone:(NSZone *)zone 
{ 
    MyClass *copy = [[MyClass alloc] init]; 

    // deep copying object properties 
    copy.objectPropertyOne = [[self.objectPropertyOne copyWithZone:zone] autorelease]; 
    copy.objectPropertyTwo = [[self.objectPropertyTwo copyWithZone:zone] autorelease]; 
        ... 
    copy.objectPropertyLast = [[self.objectPropertyLast copyWithZone:zone] autorelease]; 

    // deep copying primitive properties 
    copy.primitivePropertyOne = self.primitivePropertyOne 
    copy.primitivePropertyTwo = self.primitivePropertyTwo 
        ... 
    copy.primitivePropertyLast = self.primitivePropertyLast 

    // deep copying object properties that are of type MyClass 
    copy.myClassPropertyOne = self.myClassPropertyOne 
    copy.myClassPropertyTwo = self.myClassPropertyTwo 
        ... 
    copy.myClassPropertyLast = self.myClassPropertyLast 


    return copy; 
} 

Pero observe cómo las propiedades de la misma clase que self y copy deben configurarse sin copyWithZone :. De lo contrario, estos objetos volverán a invocar copyWithZone e intentarán establecer sus propiedades myClass utilizando también copyWithZone. Esto desencadena un bucle infinito no deseado. (Además, puede llamar a allocWithZone: en lugar de alloc: pero estoy bastante seguro de que alloc: llama a allocWithZone: de todos modos)

Hay algunos casos en los que usar = para copiar profundamente propiedades de objeto de la misma clase podría no ser lo lo que quiere hacer, pero en TODOS LOS CASOS (que yo sepa) la copia profunda de propiedades de objeto de la misma clase con copyWithZone: o cualquier cosa que llame a copyWithZone: dará como resultado un ciclo infinito.

Cuestiones relacionadas