ARC – ¿El significado de __unsafe_unretained?

Solo quiero asegurarme de que lo hice bien:

  1. ¿Debo __unsafe_unretain objetos que no me __unsafe_unretain ?
  2. Si un objeto es __unsafe_unretained ¿Necesito usar assign en @property ? ¿Eso significa que el objeto no se retiene y solo se refiere al objeto que le asigné?
  3. ¿Cuándo querría usarlo, excepto de delegates?
  4. ¿Es eso algo de ARC o estaba en uso antes?

El Comstackdor 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 Joshua indica, por defecto todos los apuntadores están implicados en __strong bajo ARC. Esto significa que cuando se asigna un objeto a ese puntero, se conserva durante el tiempo que ese puntero se refiera a él. Esto está bien para la mayoría de las cosas, pero abre la posibilidad de retener los ciclos, como describo en mi respuesta aquí . Por ejemplo, si tiene un objeto que contiene otro objeto como una variable de instancia, pero ese segundo objeto tiene un fuerte vínculo 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 delegates, donde debe definir una propiedad para ese delegado con el atributo weak o unsafe_unretained ( assign es efectivamente unsafe_unretained ), y luego hacer coincidir eso marcando la variable de instancia respectiva con __weak o __unsafe_unretained . Esto significa que la variable de instancia de delegado seguirá apuntando hacia atrás en el primer objeto, pero no hará que ese objeto sea retenido, rompiendo así el ciclo de retención y permitiendo que ambos objetos sean liberados.

Más allá de los delegates, esto es útil para romper cualquier otro ciclo de retención que pueda formarse en su código. De forma útil, el instrumento Leaks ahora incluye una vista de ciclos, que muestra los ciclos de retención que descubre en su aplicación de una manera gráfica.

Tanto __unsafe_unretained como __weak previenen la retención de objetos, pero de maneras ligeramente diferentes. Para __weak , el puntero a un objeto se convertirá en nil en la desasignación del objeto al que apunta, que es un comportamiento muy seguro. Como su nombre lo indica, __unsafe_unretained continuará apuntando a la memoria donde estaba un objeto, incluso después de que fue desasignado. Esto puede provocar lockings debido al acceso a ese objeto desasignado.

¿Por qué __unsafe_unretained entonces? Desafortunadamente, __weak solo es compatible con iOS 5.0 y Lion como destinos de despliegue. Si desea orientar nuevamente a iOS 4.0 y Snow Leopard, debe usar el calificador __unsafe_unretained , o usar algo como MAZeroingWeakRef de Mike Ash.

  1. No, también podrías usar weak para objetos que no te pertenecen.
  2. No, también podría usar unsafe_unretained en la propiedad.
  3. Tengo entendido que los elementos no unsafe_unretained que no se han unsafe_unretained son igual de weak , sin la seguridad adicional de eliminarlos cuando se libera el elemento que señalan (y la sobrecarga que lo acompaña).
  4. Esto es completamente una cosa de ARC.

__unsafe_unretained es idéntico a lo que era el almacenamiento predeterminado de un objeto antes de ARC. Con ARC, el valor predeterminado ahora es __strong lo que significa que tiene una referencia hasta que su referencia queda fuera del scope.

Otra observación en __unsafe_unretained: ¡Tengo lockings en mi aplicación en el dispositivo y NO en el simulador con iVars declarado como __unsafe_unretained! Sí, era un error en el código de la migración de ARC, pero fue la primera vez que noté la diferencia entre el dispositivo y el simulador.