2009-02-25 15 views
16

Estoy mirando la aplicación de ejemplo EditableDetailView de Apple, y me di cuenta de que en uno de sus controladores están configurando una instancia de la propiedad NSString con (no atómica, copia). ¿Cuándo se usaría una copia en lugar de retener? ¿Esto es para que puedan hacer una copia única sin afectar los datos existentes?NSString @property, usando copy en lugar de retener

+2

La recomendación es utilizar copy para las clases que forman parte de un clúster de clase que tienen pares mutables/inmutables; como 'NSString' /' NSMutableString' 'NSArray' /' NSMutableArray' 'NSDictionary' /' NSMutableDictionary' 'NSSet' /' NSMutableSet', ver la respuesta de @ Abizern [HERE] (http://stackoverflow.com/questions/4995254/nsmutablestring-as-reten-copy). – Kjuly

Respuesta

38

Sí, es para que pueda hacer una copia única sin afectar los datos existentes. Los huéspedes del sintetizados esencialmente el siguiente aspecto:

// For @synthesize(nonatomic, retain) foo: 
- (void) setFoo(NSFoo *theFoo) 
{ 
    [theFoo retain]; // retain new value 
    [foo release]; // release old value, if any 
    foo = theFoo;  // assign new value 
} 

// For @synthesize(nonatomic, copy) foo: 
- (void) setFoo(NSFoo *theFoo) 
{ 
    NSFoo* newFoo = [theFoo copy]; // make copy 
    [foo release]; // release old value, if any 
    foo = newFoo; // assign new value 
} 

Nota del orden de las operaciones aquí es importante - el nuevo valor debe ser retenido/copiado antes de liberar el valor de edad, en caso de auto-asignación. Si soltó primero y luego se asignó la propiedad a sí mismo, puede desasignar el valor por accidente. También tenga en cuenta que si el valor anterior es nil, enviar un mensaje release es correcto, ya que el envío de un mensaje a un objeto nil está explícitamente permitido y no hace nada.

La opción de retención versus copia solo determina si la propiedad del objeto comparte o no el mismo valor con el que lo está configurando. Considere el siguiente código:

// suppose the 'foo' property is declared 'retain' and the 'bar' property is 
// declared 'copy' 
NSFoo *foo = ...; 
NSBar *bar = ...; 
someObject.foo = foo; 
someObject.bar = bar; 
[foo changeInternalState]; // someObject.foo also changes, since it's the same object 
[bar changeInternalState]; // someObject.bar does NOT change, since it's a copy 
+0

puede haber un error tipográfico en su última línea. donde //someObject.foo NO ... debe ser //someObject.bar NO –

+0

Para poder invocar 'copy' en un objeto Class personalizado, debe anular el método' copyWithZone: '. – thesummersign

3

Recuerde que hay una NS mutable cadena. Sería realmente malo poder mutar el contenido de una cadena que otro objeto posee (digamos, eliminando la mitad de sus caracteres), especialmente si no te das cuenta de que estás afectando a otro objeto. Por lo tanto, es bueno que el otro objeto haga su propia copia.

Puede decir "bueno, ¿por qué no copio la cadena antes de asignarla allí?". Tal vez el objeto quiera una cuerda mutable y la tuya sea inmutable. Si primero tiene que copiar la cadena, debe buscar qué tipo de cadena quiere en su documentación o encabezado, y luego hacer el tipo correcto de copia (cada vez). De esta manera, solo diga other.string = myString y hace cualquier tipo de copia que desee; no tiene que preocuparse por ello.

0

(Por alguna razón, este post está apareciendo por encima de la pregunta de seguimiento que estoy tratando de responder) Re:

Quiso decir que tengo que copiar 'el foo' objeto antes de soltar 'foo' ?? pero ¿cuál es el problema si relaese 'foo' antes de copiar 'el foo'? Porque son dos objetos diferentes no puedo entender por qué liberando uno afecta a otro !!!!

La mayoría de las veces, estás en lo cierto. Si son, de hecho, dos objetos separados, no importará. El problema radica en la posibilidad de que estés asignando el mismo objeto a sí mismo. Si tuviera que decir

[myObject setFoo: moof]; 
[myObject setFoo: moof]; 

Luego, la segunda vez que lo hizo, liberaría el moof antes de copiarlo. En el momento intermedio, es posible que si el conteo de retenciones de moof pasara a cero, se eliminaría el moof y no tendría nada que copiar en el siguiente paso. Foo ahora sería nulo.

¿Es probable que esto suceda? Probablemente más de lo que piensas. Ciertamente, hay momentos en que el usuario puede hacer clic dos veces en un botón de "actualización", por ejemplo.

Espero que esto sea comprensible y útil.

+1

Stack Overflow es un sitio de preguntas y respuestas, no un foro. Respuestas, de las cuales tanto esta como la "pregunta" a la que usted quiso responder, están ordenadas por votos por defecto. El tuyo tiene 0 y la otra respuesta (que ahora se elimina) terminó en -3, por lo que el tuyo aparece más alto (para aquellos de nosotros con suficiente karma para ver al otro en absoluto). La forma correcta habría sido comentar la otra respuesta, pero eso requiere 50 puntos de reputación, que no tiene. (Además, su respuesta es demasiado profunda y tiene un formato rico para encajar en un comentario). No hay una forma correcta en su situación. –

Cuestiones relacionadas