objective c - ¿Uso válido de accessors en los métodos init y dealloc?
objective-c properties (2)
Entiendo que Apple considera que el comportamiento actual de 10.5 bajo el cual los ivars sintetizados no son accesibles directamente es un error; Debes poder acceder directamente a él, pero no puedes.
Por lo tanto, debe ser capaz de hacer:
someObject = nil;
en lugar de
self.someObject = nil;
Mientras tanto, usar el elemento de acceso directamente es la única forma de hacerlo sin proporcionar un ivar explícito.
Actualización : Este error ha sido corregido; Ahora puedes hacer someObject = nil
simplemente bien.
He escuchado de varias fuentes (stackoverflow.com, cocoa-dev, la documentación, blogs, etc.) que es "incorrecto" usar accesores y configuraciones (foo, setFoo :) en sus métodos init y dealloc. Entiendo que existe una posibilidad remota de confundir otros objetos que están observando la propiedad si lo hace. (Un ejemplo simple se da here )
Sin embargo, debo decir que no estoy de acuerdo con esta práctica por la siguiente razón:
El nuevo tiempo de ejecución de Objective-C (el del iPhone y el tiempo de ejecución de 64 bits en 10.5) le permite declarar propiedades sin declarar un ivar correspondiente. Por ejemplo, la siguiente clase se compilará bien en 10.5 o para el iPhone (dispositivo, no simulador):
@interface Foo : NSObject { }
@property (retain) id someObject;
@end
@implementation Foo
@synthesize someObject;
@end
Entendiendo que lo anterior es una clase Objective-C perfectamente válida, digamos que decido escribir un inicializador, y para propósitos de administración de memoria, un método de desasignación (ya que GC no está disponible en el iPhone). Todo lo que he leído sobre los inicializadores y la dislocación me llevaría a escribir los siguientes dos métodos:
- (id) init {
if (self = [super init]) {
//initialize the value of someObject to nil
[self setSomeObject:nil];
}
return self;
}
- (void) dealloc {
//setting someObject to nil will release the previous value
[self setSomeObject:nil];
[super dealloc];
}
Sin embargo, según la documentación y la opinión popular, esto es "incorrecto". Así que mis preguntas son las siguientes:
- ¿Cómo se supone que debo inicializar algún objeto sin utilizar el descriptor de acceso? Podría decir que el compilador (o el tiempo de ejecución o lo que sea) se asegurará de que someObject ya esté configurado en nulo, pero creo que sería un comportamiento inadecuado confiar en eso. Teniendo un historial decente en C, he visto un buen número de errores debido a que no se inicializan correctamente las variables, y esto parece poco diferente.
- ¿Cómo puedo liberar someObject si no debo usar el método de acceso en el método dealloc?
Si la respuesta a cualquiera de estos es "no se puede", ¿cómo puede ser malo usar accesores en sus métodos init y dealloc?
EDITAR (13 de febrero de 2013): Como se señala en mi comentario a continuación, y especialmente desde la adición de ARC, he cambiado de opinión al respecto. Antes de ARC, vi muchos errores que causaban fallos debido a asignaciones de ivar incorrectas en init
. OMI, especialmente trabajando con equipos junior, los problemas raros con el uso de los accesores en init
fueron superados por los errores comunes de acceso ivar. Dado que ARC ha eliminado este tipo de errores, los errores raros pero posibles que puede causar el uso de accessor en init
son más importantes, por lo que he cambiado a admitir el uso directo de ivars en init
y dealloc
, y solo en esos lugares. ; accesores en cualquier otro lugar que sea posible (obviamente, no puede usar los accesores dentro del mismo accesor ...)
Respuesta PRE-ARC
Estoy totalmente en desacuerdo con aquellos que se oponen a los -init
en -init
. En casi todos los casos, este es un muy buen lugar para usar los accesores, y guarda muchos errores que he visto en los nuevos codificadores de Cocoa que invariablemente no pueden retener al asignar in- -init
.
-dealloc
es una llamada más dura. Tengo una inclinación natural a usar los accesores allí (para que se usen en todas partes), pero puede causar dolores de cabeza debido a KVO (o incluso a notificaciones de NS si publica una notificación de cambio en su configurador). Dicho esto, aunque no uso los -dealloc
en -dealloc
, lo considero muy discutible y Apple es muy inconsistente al respecto (sabemos que están llamando setView:
en UIViewController -dealloc
por ejemplo).
En cualquier caso, diría que el uso insuficiente de los elementos de acceso ha causado 100 veces los errores de uso excesivo. Siempre me equivocaría en usarlos, excepto cuando hay una razón importante para no hacerlo.