ETA: @DougW señala correctamente que de una propiedad tipo de propiedad (assign
/retain
/copy
) no afecta al comprador. Todavía afecta al colocador. Para los tipos readonly
, esto importa si va a anular la parte readonly
de la declaración en una extensión de clase, para que pueda usar el setter en su implementación. La anulación de propiedad de extensión de clase solo permite cambiar el estado readonly
de la propiedad, por lo que el resto, es decir, la atomicidad y los tipos de propiedad, deben declararse adecuadamente en el encabezado. Incluso si no está anulando la propiedad ahora, podría hacerlo en el futuro, por lo que también podría documentar cómo desea que se administre la memoria utilizando la opción correcta para comenzar.
El recuento automático de referencias (ARC) cambia los detalles de implementación en tiempo de ejecución superponiendo sus propias reglas de administración de memoria además de las reglas de refcount clásicas, pero las reglas y consejos para configurar sus propiedades siguen siendo las mismas.
¿Por qué utilizar retain
con readonly
? Si marca una propiedad como retain
, el descriptor de acceso sintetizado hace algo como esto:
/* getter for retain property */
- (NSString *)name {
return [[name retain] autorelease];
}
Ahora bien, si el objeto que envió a -name
cambia el nombre, mientras que todavía se esté usando, el código de llamada todavía tendrá una referencia válida a una cadena.Si lo declaró como assign
, sin embargo, sería la siguiente:
/* getter for assign property */
- (NSString *)name {
return name;
}
Ahora, tan pronto como el nombre se cambió por el objeto, éste tendrá que ser puesto en libertad para evitar una fuga, lo que invalidará la llamada referencia del código El retain
/copy
/assign
realmente establece una política de gestión de memoria: retain
/copy
dice: "Prometo que tengo una referencia al original/una copia del valor que proporciono aquí", mientras que assign
dice: "Simplemente tengo el valor y reclamo no poseer referencia de esto ".
Cuando el valor no necesita gestión de memoria, como un simple int
, entonces assign
tiene sentido. Cuando intencionalmente no está reteniendo un objeto, como un delegado, entonces assign
tiene sentido. Pero, en la mayoría de los demás casos, querrá retain
o copy
.
Además, el archivo de implementación solo puede anular la parte readwrite
/readonly
de una declaración de propiedad, no la parte de administración de memoria. Según lo declarado, el archivo puede tener .m
:
setters para las declaraciones de bienes sobrescritos
@interface Holiday (/*class extension*/)
@property(nonatomic, retain, readwrite) NSDate *date;
/* override other properties to make them readwrite... */
@end
no públicas luego serán sintetizados junto con los descriptores de acceso públicos.
¿Por qué no utilizar arregladores/accesorios durante -init
? Dado que los programadores/accededores realizan con frecuencia la notificación KVO, que desea evitar mientras el objeto no está completamente inicializado, es decir, durante -init
(cuando está medio iniciado en su camino a la inicialización completa) y -dealloc
(cuando está semiautomatizado en su forma de ser completamente sin inicializar).
¿Por qué usar copy
con readonly
? Como respuesta a su primera pregunta: porque si copy
versus retain
contra assign
afecta tanto a los instaladores como a los getters. Un captador de copia se vería así:
/* getter for copy property */
- (NSString *)name {
return [[name copy] autorelease];
}
Por qué a veces ya veces copy
retain
?copy
se usa generalmente con objetos de valor (objetos pasivos que representan un valor); retain
se usa generalmente con otros objetos. Algunas veces, las preocupaciones sobre la eficiencia entran en juego (muy probablemente prematuramente ...), y puede optar por usar retain
donde normalmente usaría copy
.
¿Cómo usarías copy
/retain
junto con readonly
aquí? Más o menos como lo hicieron. Anularía las declaraciones en una extensión de clase para que pueda usar setters para cambiar los valores de las propiedades fuera de -init
y -dealloc
, donde solo usaría el acceso directo a la variable de instancia. Lo haría también nil
los Ivars después de la liberación de ellos en -dealloc
, por ejemplo,
[name release], name = nil;
Esto ayuda a evitar el envío de mensajes o de otra manera a hacer referencia a un objeto lanzado ya.
** nonatomic ** propiedades de retención solo devuelve el puntero. Ellos ** no ** hacen lo de retener, lanzar automáticamente. Consulte la sección ** atomicity ** de los documentos http://developer.apple.com/library/ios/# documentation/cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html – JeremyP
@JeremyP: Buena llamada. La decisión de no '[[foo retener] liberación automática] 'en accesadores no atómicos tiene sentido: si va a conservar el valor durante más tiempo que el ciclo de ciclo de ejecución actual, debe conservarlo usted mismo. Si está utilizando 'no atómico', básicamente está diciendo que la seguridad de la secuencia no es una preocupación. Si no tiene que preocuparse por la seguridad de las hebras, entonces no se ejecutará ningún código aparte del suyo mientras esté usando el valor devuelto por el descriptor de acceso, por lo que no es necesario que el descriptor de acceso ejecute '[[foo retener] liberación automática]' . –
@Jeremy: iría tan lejos como para decir que el uso no atómico significa que está diciendo que la solidez no es una preocupación, o es una preocupación menor que el rendimiento. Establecer propiedades no atómicas sin un primer perfil de su código cuenta como una optimización prematura en mi libro. – JeremyP