2011-10-07 12 views
35

Hay una pregunta similar a esta en SO here, sin embargo, solo quiero aclarar algo que no se explicó completamente allí.IBOutlet y viewDidUnload bajo ARC

Entiendo que todos los delegados y puntos de venta - de hecho, cualquier referencia a un objeto "padre", ser un buen ciudadano y pensar en el gráfico de objetos por un minuto - debe poner a cero las referencias débiles. Debido a la naturaleza de la puesta a cero de punteros débiles que caen automáticamente a cero en el recuento de retención del objeto al que se hace referencia que llega a cero, ¿significa esto que establecer IBOutlets en cero en viewDidUnload ahora no es necesario?

lo tanto, si yo anuncio mi salida de este modo:

@property (nonatomic, weak) IBOutlet UILabel *myLabel; 

¿El siguiente código tiene ningún efecto?

- (void)viewDidUnload 
{ 
    self.myLabel = nil; 

    [super viewDidUnload]; 
} 
+0

Me agradaría saber el motivo del voto a la baja? – Stuart

+0

Tenía curiosidad por la respuesta, así que voté para contrarrestarla. No sé la respuesta ... – bryanmac

Respuesta

15

Sólo con hacer un poco de investigación ...

Como lo entiendo, débil es similar a asignar, en el que los dos son referencias débiles.

Sin embargo, asignar no crea una referencia de puesta a cero. es decir, si el objeto en cuestión se destruye y usted accede a esa propiedad, obtendrá un BAD_ACCESS_EXCEPTION.

Las propiedades débiles se ponen a cero automáticamente (= nil) cuando se destruye el objeto al que hace referencia.

En ambos casos, no es necesario establecer la propiedad en cero, ya que no contribuye al conteo de retención del objeto en cuestión. Es necesario cuando se usan propiedades de retención.

Aparentemente, ARC también presenta una nueva propiedad "fuerte", que es lo mismo que "retener"?

investigación realizada here

+1

Gracias por la respuesta. Entiendo el funcionamiento de la referencia débil, mi pregunta está más relacionada con los mecanismos que subyacen 'viewDidUnload'. En otras palabras, ¿es siempre el caso que la vista forzará la referencia débil a 'nil' directamente después de la llamada' viewDidUnload'? – Stuart

+2

Nuevamente, ** según lo entiendo **, la Vista y sus SubViews se lanzarán cuando se elimine de la pantalla. Dado que, débil no incrementa la cuenta de liberación, y se pone a cero cuando se destruye su referencia, no debería ser necesario. –

+1

Lo siento, debo haber perdido esa parte de su respuesta cuando la leí la primera vez. – Stuart

11

hice una pequeña prueba y parece que el código en el método viewDidUnload es innecesaria. Para respaldar esto, los documentos para viewDidUnload realmente dicen:

En el momento en que se invoca este método, la propiedad de vista es nula.

que indica que la referencia débil debe haberse establecido en nil automáticamente.

+3

Esto también lo entiendo. ¿Pero por qué entonces Xcode inserta sentencias '[self setMySubview: nil]' en 'viewDidUnload' cuando crea puntos débiles? –

+2

Creo que podría ser una característica que queda del código previo al ARC, de la misma manera que cuando le pides a Xcode que genere una subclase 'NSManagedObject' para Core Data, las propiedades generadas están configuradas para' retener' en lugar de 'strong '. Aunque en el caso de los puntos de venta, _se_ crean como 'débiles'. Mi suposición es que no es intencional. – Stuart

+0

Estoy de acuerdo. Es probable que la interfaz de usuario del Interface Builder esté pasando por alto con precaución al arrastrar y colocar para crear salidas en el código. Esas configuraciones nulas se pueden eliminar de forma segura siempre que use ARC y referencias débiles en las salidas en cuestión. –

3

Desde mi entendimiento de cómo se administran las tomas en ARC si está utilizando una referencia débil, no necesita agregar nada para verDidUnload ya que será nulo. Hacerlo es por lo tanto redundante.

Sin embargo, si tiene enchufes fuertes, que Apple dice que debe hacer si apunta a un elemento de nivel superior en la punta, entonces definitivamente debe continuar agregando la línea adecuada en viewDidUnload para anular estos.

+0

Quiero saber, si he definido esto '@property (no atómico, fuerte) IBOutlet UILabel * myLabel;', ¿necesito definir 'self.myLabel = nil;' en la función 'viewDidUnload'. – BlackMamba

5

Tengo alguna evidencia empírica para apoyar que IBOutlets ya están configurados en nil automáticamente. Esto es lo que hice:

  1. puedo configurar Ivars explícitas para mis propiedades IBOutlet (@synthesize myLabel = myLabel_) para que pueda inspeccionar sus valores más adelante en el depurador.
  2. He habilitado un punto de interrupción en la primera línea de viewDidUnload.
  3. Dispuse para viewDidUnload para llamar al simular una advertencia de memoria.
  4. Inspeccioné los valores de los ivars explícitos que asocié a mis propiedades de IBOutlet.

Los ivars explícitos todos tenían nil como su valor, luego llegué al punto de interrupción.

0

A partir de iOS 5 y OS X 10.7, weak producirá un puntero de puesta a cero automática. Esto significa que cuando se libera el objeto puntiagudo, el puntero se configura automágicamente en nil (para detalles, ver Zeroing Weak References in ARC).

Así, bajo iOS 5+ y OS X 10.7 o versiones posteriores, no es útil para establecer las propiedades de weakIBOutletnil manualmente en el método viewDidUnload: cuando se descarga la vista principal, todas sus subvistas se dará a conocer, por lo que la las propiedades relacionadas se establecen en nil.

Cuestiones relacionadas