ios - débil o fuerte para IBOutlet y otro
ios5 automatic-ref-counting (2)
Esta pregunta ya tiene una respuesta aquí:
- ¿IBOutlets debería ser fuerte o débil bajo ARC? 11 respuestas
Cambié mi proyecto a ARC, y no entiendo si tengo que usar strong
o weak
para IBOutlets. Xcode hace esto: en el constructor de interfaces, si creamos un UILabel
por ejemplo y lo conecto con el editor asistente a mi ViewController
, crea esto:
@property (nonatomic, strong) UILabel *aLabel;
Utiliza el strong
, en su lugar, leí un tutorial en el sitio web RayWenderlich que dice esto:
Pero para estas dos propiedades en particular, tengo otros planes. En lugar de ser
strong
, los declararemos comoweak
.
@property (nonatomic, weak) IBOutlet UITableView *tableView;
@property (nonatomic, weak) IBOutlet UISearchBar *searchBar;
Weak
es la relación recomendada para todas las propiedades de salida . Estos objetos de vista ya son parte de la jerarquía de vista del controlador de vista y no necesitan ser retenidos en otro lugar. La gran ventaja de declarar que sus puntos de venta sonweak
es que le ahorra tiempo escribir el método viewDidUnload.Actualmente, nuestra
viewDidUnload
tiene este aspecto:
- (void)viewDidUnload
{
[super viewDidUnload];
self.tableView = nil;
self.searchBar = nil;
soundEffect = nil;
}
Ahora puede simplificarlo a lo siguiente:
- (void)viewDidUnload
{
[super viewDidUnload];
soundEffect = nil;
}
Así que use weak
, en lugar de strong
, y elimine el set en nil en la videDidUnload
, en cambio Xcode use el strong
, y use el self... = nil
en viewDidUnload
.
Mi pregunta es: ¿cuándo debo usar strong
y cuándo weak
? También quiero utilizar para el destino de despliegue iOS 4, así que, ¿cuándo debo usar el unsafe_unretain
? ¿Alguien puede ayudarme a explicarme bien con un pequeño tutorial, cuando use strong
, weak
e unsafe_unretain
con ARC?
Puede usar weak para objetos que están conectados a través de IBOutlets a objetos en IB porque en este caso los objetos estarán allí mientras la superview 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 que eche un vistazo a los videos de WWDC11 y WWDC12. Otro buen recurso es el podcast de desarrollo iOS de Stanford.
Una regla de oro
Cuando un padre tiene una referencia a un objeto hijo, debe usar una referencia strong
. Cuando un niño tiene una referencia a su objeto principal, debe usar una referencia weak
o una no unsafe_unretained
(si la primera no está disponible). Un escenario típico es cuando tratas con delegados. Por ejemplo, un UITableViewDelegate
no conserva una clase de controlador que contiene una vista de tabla.
Aquí un esquema simple para presentar los conceptos principales.
Supongamos que primero A, B y C son referencias strong
. En particular, C tiene una 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 conteos de retención ( solo para propósitos de explicación ), obj1 tiene un conteo de retención de 2 (obj2 tiene una referencia strong
), mientras que obj2 tiene un conteo de retención de 1. Si se libera obj1, su conteo de retención es ahora 1 y su método dealloc
no es llamado. obj1 y obj2 aún permanecen en la memoria, pero nadie tiene una referencia a ellos: fuga .
En el contrato, si solo A y B son referencias strong
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 retenido es ahora 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 trabaje con ARC.
Sobre su primera pregunta, ambas soluciones son válidas cuando trata con XIB. En general, weak
referencias weak
se utilizan cuando se trata de ciclos de memoria. Con respecto a los archivos XIB, si usa strong
necesita establecer nil
en viewDidUnload
ya que si no lo hace, en condiciones de poca memoria, podría causar pérdidas inesperadas. No los libera en dealloc
porque ARC lo hará por usted. weak
cambio, no necesita ese tratamiento ya que, cuando se destruye el objeto de destino, esos valores se establecen como nil
automática. Ya no hay punteros colgantes.
Si está interesado, realmente le sugiero que lea friday-qa-2012-04-13-nib-memory-management por Mike Ash .
Sobre su segunda pregunta, si necesita soportar iOS 4, en lugar de weak
, debe usar unsafe_unretained
.
Dentro de SO hay muchas preguntas / respuestas. Aquí los principales:
¿Cómo reemplazo las referencias débiles cuando uso ARC y apunte a iOS 4.0?
¿Qué tipo de fugas evita o minimiza el conteo automático de referencias en Objective-C?
usando ARC, asignar calificador de por vida y inseguro_unretenido
strong / weak / retain / unsafe_unretained / assign
Espero que ayude.
Actualizar
Según el comentario de shaunlim, a partir de iOS 6 el método viewDidUnload
está en desuso. Aquí realmente sugiero ver la respuesta de Rob: iOS 6: viewDidUnload migrate to didReceiveMemoryWarning? .