Es posible que esos ejemplos usen la retención porque el código de muestra asigna e inicializa programáticamente un UILabel y luego lo agrega a UIView. Ese es el caso de muchos ejemplos, ya que aprender a usar Interface Builder a menudo no es su objetivo.
El segundo ejemplo (sin propiedad y sin sintetizar) con IBOutlet se utiliza cuando el desarrollador 'asigna' el UILabel (botón, vista, etc.) dentro del Interface Builder, arrastrando el IBOulet hasta la etiqueta u otra vista. componente. En mi opinión, la acción anterior de arrastrar y soltar (Etiqueta en vista) también agrega la subvista, la Etiqueta a una vista, y así sucesivamente. La etiqueta es retenida por una Vista; una Vista es retenida por Window; La ventana es retenida por el propietario del archivo. El propietario del archivo suele ser su documento que se inicia en principal.
Usted notará que cuando paso a través de su programa (mediante la adición de un awakeFromNib
- (void)awakeFromNib
{
[fooLabel blahblah];
}
que fooLabel ya tiene una dirección de memoria.
Eso es debido a que la etiqueta se ha inicializado de un lote de archivos (el archivo nib) utilizando no init pero initWithCoder. Esto esencialmente deserializa el filestream a un objeto y luego establece la variable IBOutlet. (Todavía estamos hablando del método IBOutlet)
También tenga en cuenta que el iOS mencionado anteriormente thod utiliza el método de valor clave
call [object setValue:outletValue forKey:@"<OutletName>"]
que es el patrón Observer/Observable. Ese patrón requiere que el Objeto Observable haga referencia a cada Observer en un Conjunto/Matriz. Un cambio de valor repetirá el Conjunto/Matriz e igualmente actualizará todos los Observadores. Ese conjunto ya retendrá a cada observador por lo tanto la falta de retención en iOS.
Además y el resto es especulación.
Parece que los casos cuando se hace uso de Interface Builder entonces
@property (nonatomic, retain) IBOutlet UILabel *fooLabel;
posiblemente se debe cambiar a
@property (nonatomic, weak) IBOutlet UILabel *fooLabel;
o @property (no atómica, asignar) IBOutlet UILabel * fooLabel;
Y luego no necesita ser lanzado en un método dealloc. Además, satisfará los requisitos de OSX e iOS.
Eso está basado en la lógica y podría faltar algunas piezas aquí.
Sin embargo, puede no importar si la vista es persistente durante la vida de su programa. Mientras que una etiqueta en un cuadro de diálogo modal (abrir, cerrar, abrir, cerrar) de hecho puede haber retenido demasiado y tener fugas por ciclo. Y eso es porque (especulación otra vez) cada cuadro de diálogo cerrado se serializa en un sistema de archivos y por lo tanto persiste x, y posición y tamaño, junto con sus subvistas, etc. Y posteriormente se deserializa ... en la siguiente sesión abierta (Opuesto a decir minimiz u oculto.)
Hola Jon, ¡Gracias por la respuesta detallada! Muy útil –
¿Qué sucede si el nombre de la variable es diferente del nombre de la propiedad? ¿Importa si es diferente? –
El nombre anterior "OutletName" se define como lo que está junto a la palabra clave "IBOutlet" en el código fuente. Si IBOutlet está en @property, no importa el nombre de la variable de instancia dado que se encontrará un setter. Si por alguna razón no existiera un colocador, se produciría una excepción al conectar el tomacorriente. Si la palabra clave IBOutlet está en la variable de instancia, y existe un setter con un nombre que no coincide, no se llamará al setter. –