iphone - guide - objective c documentation
NSString @property, utilizando copia en lugar de retener (3)
Estoy mirando la aplicación de ejemplo EditableDetailView de Apple y noté que en uno de sus controladores, están configurando una instancia de propiedad NSString con (no atómico, copia). ¿Cuándo se usaría copiar en lugar de retener? ¿Esto es así para que puedan hacer una copia única sin afectar los datos existentes?
(Por alguna razón, esta publicación aparece encima de la pregunta de seguimiento que estoy tratando de responder) Re:
¿quiso decir que tengo que copiar el objeto ''foo'' antes de soltar ''foo''? pero ¿cuál es el problema si creo que ''foo'' antes de copiar ''foo''? porque son dos objetos diferentes, no puedo entender por qué liberando uno afecta al otro !!!!
La mayoría de las veces, estás en lo correcto. Si son, de hecho, dos objetos separados, no importará. El problema radica en la posibilidad de que esté asignando el mismo objeto de nuevo a sí mismo. Si fueras a decir
[myObject setFoo: moof];
[myObject setFoo: moof];
Luego, la segunda vez que lo hiciste, soltarías Moof antes de copiarlo. En el momento intermedio, es posible que si el recuento de retención de moof se redujera a cero, se eliminaría 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 ocasiones en que el usuario puede hacer clic en un botón "actualizar" dos veces, por ejemplo.
Espero que esto sea comprensible y útil.
Recuerda que hay un NS Mutable String. Sería realmente malo poder mutar el contenido de una cadena que posee otro objeto (por ejemplo, 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.
Puedes decir "bueno, ¿por qué no copio la cadena antes de asignarla allí?". Tal vez el objeto quiera una cuerda mutable y la suya sea inmutable. Si primero tiene que copiar la cadena, debe buscar qué tipo de cadena desea en su documentación o encabezado, y luego hacer la copia correcta (cada vez). De esta manera, solo dices other.string = myString
y other.string = myString
cualquier tipo de copia que desee, no tienes que preocuparte por eso.
Sí, es para que pueda hacer una copia única sin afectar los datos existentes. Los setters sintetizados esencialmente se ven así:
// 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
}
Tenga en cuenta que el orden de las operaciones aquí es importante: el nuevo valor debe conservarse / copiarse antes de que se libere el valor anterior, en caso de autoasignación. Si liberó primero y luego se asignó la propiedad a sí mismo, podría desasignar el valor por accidente. También tenga en cuenta que si el valor anterior es nil
, el envío de un mensaje de release
está bien, ya que el envío de un mensaje a un objeto nil
está explícitamente permitido y no hace nada.
La opción de retener frente a copiar simplemente determina si la propiedad del objeto comparte o no el mismo valor con lo 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