31

He cambiado mi proyecto a ARC, y no entiendo si tengo que usar strong o weak para IBOutlet. Xcode hacer esto: en el constructor de interfaces, si un crear un UILabel por ejemplo, y lo conecto con el asistente editor para mi ViewController, que crean esto:débil o fuerte para IBOutlet y otros

@property (nonatomic, strong) UILabel *aLabel; 

Utiliza el strong, en vez leí un tutorial en el sitio web RayWenderlich que dicen esto:

Pero para estas dos propiedades en particular, tengo otros planes. En lugar de strong, los declararemos como weak.

@property (nonatomic, weak) IBOutlet UITableView *tableView; 
@property (nonatomic, weak) IBOutlet UISearchBar *searchBar; 

Weak es la relación recomendada para todos los propiedades de salida. Estos objetos de vista ya forman parte de la jerarquía de vista del controlador de vista y no es necesario que se conserven en otro lugar. La gran ventaja de de declarar sus salidas weak es que le ahorra tiempo escribir el método viewDidUnload.

Actualmente nuestra viewDidUnload se parece a esto:

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    self.tableView = nil; 
    self.searchBar = nil; 
    soundEffect = nil; 
} 

Ahora puede simplificar a la siguiente:

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    soundEffect = nil; 
} 

Así que utilice weak, en lugar de la strong, y elimine el conjunto a cero en el videDidUnload, en lugar de e strong, y use self... = nil en el viewDidUnload.

Mi pregunta es: cuándo tengo que usar strong, y cuándo weak? También quiero usar para el destino de despliegue iOS 4, entonces ¿cuándo debo usar el unsafe_unretain? ¿Alguien puede ayudarme a explicarme bien con un pequeño tutorial, cuando use strong, weak y unsafe_unretain con ARC?

Respuesta

69

Una regla de oro

Cuando un padre tiene una referencia a un objeto secundario, se debe utilizar una referencia strong. Cuando un niño tiene una referencia a su objeto principal, debe usar una referencia weak o una unsafe_unretained (si la primera no está disponible). Un escenario típico es cuando tratas con delegados. Por ejemplo, un UITableViewDelegate no retiene una clase de controlador que contiene una vista de tabla.

enter image description here

Aquí un esquema simple de presentar los principales conceptos.

Supongamos que las primeras A, B y C son strong referencias. En particular, C tiene un strong referencia a su padre. Cuando obj1 se libera (en algún lugar), la referencia A ya no existe, pero tiene una fuga ya que hay un ciclo entre obj1 y obj2. Hablando en términos de retener recuentos (solo para propósitos de explicación), obj1 tiene un conteo retenido de 2 (obj2 tiene una referencia strong), mientras que obj2 tiene un retener el recuento de 1. Si obj1 se libera, su recuento retenido es ahora 1 y su método dealloc no se llama. obj1 y obj2 aún permanecen en la memoria pero nadie tiene una referencia sobre ellos: Fuga.

En el contrato, si solo A y B son strong refs y C está calificado como weak todo está bien. No tienes filtraciones De hecho, cuando se lanza obj1, también libera obj2. Hablando en términos de conteos de retención, obj1 tiene un conteo de retención de 1, obj2 tiene un conteo de retención de 1. Si se libera obj1, su conteo de retención ahora es 0 y se llama a su método dealloc. obj1 y obj2 se eliminan de la memoria.

Una sugerencia simple: Comience a pensar en términos de gráfico de objetos cuando se ocupa de ARC.

Acerca de su primera pregunta, ambas soluciones son válidas cuando se trata de XIB. En general, las referencias weak se utilizan cuando se trata de ciclos de memoria. En cuanto a los archivos XIB, si usa strong, debe configurar nil en viewDidUnload ya que si no lo hace, en condiciones de poca memoria, podría causar fugas inesperadas. No los libera en dealloc porque ARC lo hará por usted. weak en su lugar no necesita ese tratamiento ya que, cuando se destruye el objeto de destino, esos valores se establecen como nil automáticamente. Ya no hay punteros colgantes.

Si usted está interesado, realmente le sugiero que lea friday-qa-2012-04-13-nib-memory-management por Mike Ash.

Acerca de su segunda pregunta, si necesita admitir iOS 4, en lugar de weak tiene que usar unsafe_unretained.

Dentro de SO hay un montón de preguntas/respuestas.Aquí los principales:

How do I replace weak references when using ARC and targeting iOS 4.0?

What kind of leaks does automatic reference counting in Objective-C not prevent or minimize?

using ARC, lifetime qualifier assign and unsafe_unretained

strong/weak/retain/unsafe_unretained/assign

Espero que ayude.

actualización

De acuerdo con el comentario de shaunlim, a partir de iOS 6 viewDidUnload método es obsoleto. Aquí realmente sugiero ver la respuesta de Rob: iOS 6 - viewDidUnload migrate to didReceiveMemoryWarning?.

+0

gracias por la respuesta – Piero

+0

dices eso, para iboutlet si uso fuerte tengo que usar nil en viewdidunload, y para poca memoria no tengo fugas, en cambio con weak no tengo que usar nil en videwdidunlaod, y para poca memoria advirtiendo que es mejor la solución fuerte o la débil? – Piero

+0

Es lo mismo. Usar 'weak' le permite ahorrar tiempo escribiendo código (dos líneas en su caso) a mano. Pero, Xcode lo hace por ti. Mi opinión personal. Me gusta usar 'fuerte'. –

11

Puede usar weak para objetos que están conectados mediante IBOutlets a objetos en IB porque en este caso los objetos estarán allí mientras la supervista esté allí. Esto se debe a que la supervista tiene un fuerte puntero a sus subvistas.

Si el puntero que está definiendo es el único puntero a un objeto, debe declararlo como fuerte.

Si es un desarrollador registrado, le recomiendo encarecidamente que eche un vistazo a los videos de WWDC11 y WWDC12.Otro buen recurso es el podcast de desarrollo de iOS Stanford.

+0

¿Ya están disponibles los videos de WWDC12? – borrrden

+0

Sí, lo son! Muy rápido este año. – dasdom

+0

bien, pero no entiendo, mi pregunta también es insegura, pero para IBOutlet, explico bien, ¿por qué el uso de la manzana es fuerte? ... ¿en lugar de usar débil? ... ¿entonces tengo que seguir a la manzana? o siga el tutorial raywenderlich donde escribo arriba un fragmento que usa débil? – Piero

Cuestiones relacionadas