Uso válido de accesores en métodos init y dealloc?


He escuchado ahora 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 hay una posibilidad remota de confundir otros objetos que están observando la propiedad si lo hace. (se da un ejemplo simple aquí)

Sin embargo, tengo que decir que no estoy de acuerdo con esta práctica por la siguiente razón:

El nuevo Objective-C runtime (el del iPhone y el de 64 bits en 10.5) te permite declarar properties sin que declare un ivar correspondiente. Por ejemplo, la siguiente clase compilará muy 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 fines de gestión de memoria, un método dealloc (ya que GC no está disponible en el iPhone). Todo lo que he leído sobre inicializadores y desasignació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:

  1. ¿Cómo se supone que inicialice SomeObject sin usar el accessor? Se podría decir que el compilador (o tiempo de ejecución o lo que sea) se asegurará de que SomeObject ya esté establecido en nil, pero creo que sería un comportamiento inadecuado confiar en eso. Teniendo un fondo decente en C, he visto un buen número de errores debido a no inicializar correctamente las variables, y esto parece un poco diferente.
  2. ¿Cómo puedo liberar SomeObject si se supone que no debo usar el accessor en el método dealloc?

Si la respuesta a cualquiera de estos es "no puedes", entonces ¿cómo puede ser malo usar accesores en tus métodos init y dealloc?

Author: Community, 2009-08-16

2 answers

Entiendo que el comportamiento actual 10.5 bajo el cual los ivars sintetizados no son directamente accesibles es considerado por Apple como un error; debería poder acceder directamente a él, pero no puede.

Por lo tanto, usted debe ser capaz de hacer:

someObject = nil;

En lugar de

self.someObject = nil;

Mientras tanto, usar el accessor directamente es la única manera de hacerlo sin proporcionar un ivar explícito.

Actualizar : Este error se ha solucionado; ahora puedes hacer someObject = nil muy bien.

 8
Author: BJ Homer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-09 23:56:58

EDITAR (Feb 13, 2013): Como he señalado en mi comentario a continuación, y especialmente desde la adición de ARC, he cambiado de opinión sobre esto. Antes de ARC, vi muchos errores que causaban bloqueos debido a asignaciones incorrectas de ivar en init. IMO, especialmente trabajando con equipos junior, los raros problemas con el uso de accesores en init fueron superados por los errores comunes de ivar access. Dado que ARC ha eliminado este tipo de errores, los errores raros pero posibles que el uso de accessor en init puede causar son más importante, y por lo que he cambiado a apoyar el uso directo de ivars en init y dealloc, y solo en esos lugares; accessors en todas partes que es posible (obviamente no se puede utilizar accessors dentro del propio accessor....)


Respuesta ANTERIOR al ARCO

Estoy totalmente en desacuerdo con aquellos que se oponen a los accesores en -init. En casi todos los casos, este es un muy buen lugar para usar accesores, y ahorra muchos errores que he visto en los nuevos codificadores de Cacao que invariablemente fallan conservar al asignar en -init.

-dealloc es una decisión más difícil. Tengo una inclinación natural a usar accesores allí (para que se usen en todas partes), pero puede causar dolores de cabeza debido a KVO (o incluso NSNotifications si publica una notificación de cambio en su configurador). Dicho esto, aunque no uso accesores en -dealloc, lo considero muy discutible y Apple es muy inconsistente al respecto (sabemos que están llamando a setView: en el -dealloc de UIViewController, por ejemplo).

En cualquier caso, me gustaría digamos que el uso insuficiente de los accesores ha causado 100 veces los errores de uso excesivo. Siempre me equivoco al usarlos, excepto cuando hay una fuerte razón para no hacerlo.

 9
Author: Rob Napier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-13 08:05:35