El compilador LLVM 3.0 presenta cuatro nuevos calificadores de propiedad: __strong
, __autoreleasing
, __unsafe_unretained
, y __weak
. Los tres primeros están disponibles incluso fuera de ARC, según la especificación .
Como indica Joshua, de forma predeterminada, todos los punteros están implícitos __strong
en ARC. Esto significa que cuando se asigna un objeto a ese puntero, se retiene durante el tiempo que ese puntero se refiere a él. Esto está bien para la mayoría de las cosas, pero abre la posibilidad de retener ciclos, como describo en mi respuesta aquí . Por ejemplo, si tiene un objeto que contiene otro objeto como variable de instancia, pero ese segundo objeto tiene un vínculo fuerte con el primero como su delegado, los dos objetos nunca se liberarán.
Es por esta razón que existen los calificadores __unsafe_unretained
y __weak
. Su uso más común es para los delegados, donde definiría una propiedad para ese delegado con el atributo weak
o unsafe_unretained
( assign
es efectivamente unsafe_unretained
), y luego lo emparejaría marcando la variable de instancia respectiva con __weak
o __unsafe_unretained
. Esto significa que la variable de instancia delegada seguirá apuntando al primer objeto, pero no hará que ese objeto se retenga, rompiendo así el ciclo de retención y permitiendo que ambos objetos se liberen.
Más allá de los delegados, esto es útil para romper cualquier otro ciclo de retención que pueda formarse en su código. De manera útil, el instrumento Leaks ahora incluye una vista de Ciclos, que muestra los ciclos de retención que descubre en su aplicación de manera gráfica.
Ambos __unsafe_unretained
y __weak
previenen la retención de objetos, pero de formas ligeramente diferentes. Porque __weak
, el puntero a un objeto se convertirá nil
en la desasignación del objeto al que apunta, lo que es un comportamiento muy seguro. Como su nombre lo indica, __unsafe_unretained
seguirá apuntando a la memoria donde estaba un objeto, incluso después de haber sido desasignado. Esto puede provocar bloqueos debido al acceso a ese objeto desasignado.
¿Por qué lo usarías __unsafe_unretained
entonces? Desafortunadamente, __weak
solo es compatible con iOS 5.0 y Lion como destinos de implementación. Si desea volver a apuntar a iOS 4.0 y Snow Leopard, debe usar el __unsafe_unretained
calificador o usar algo como MAZeroingWeakRef de Mike Ash .
__unsafe_unretained
puede ser útil para definir matrices C deNSString
constantes y similares, por ejemploNSString __unsafe_unretained *myStrings = { @"Foo", @"Bar", @"Baz", nil };