objective-c ios ios5 objective-c-blocks automatic-ref-counting

objective c - ARC, ivars en bloques y ciclos de referencia a través de Self capturado



objective-c ios (2)

Estoy trabajando en un entorno iOS5 / ARC puro, por lo que puedo usar __ referencias débiles según sea necesario. Hago referencias a ivars en un bloque en muchas situaciones, sobre todo, bloques de animación que mueven las vistas, que son propiedades de, por ejemplo, mi clase de controlador de vista.

Mi pregunta:

En el uso más trivial de ivars en un bloque, ¿estoy creando un ciclo de referencia? ¿Debo usar la técnica __weak self / strong self cada vez que escribo un bloque que manipula las variables de instancia del objeto que contiene?

He estado revisando la sesión # 322 de la WWDC 2011 (Avances en profundidad de Objective-C) para comprender los matices con respecto al segmento de 3 minutos que comienza en el índice de tiempo 25:03 sobre "Ciclo de referencia a través del yo capturado". Para mí, esto implica que cualquier uso de ivars en un bloque debe protegerse con la configuración de self / strong self tal como se describe en ese segmento.

El siguiente método de muestra en un controlador de vista, es típico de las animaciones que hago.

En el bloque openIris, ¿es incorrecto hacer referencia a ivars “_topView” y “_bottomView” como lo he hecho?

¿Debo configurar siempre una __negua referencia a sí mismo antes del bloque, luego una referencia fuerte dentro del bloque a la referencia débil que acabo de configurar antes, y luego acceder a los ivars a través de esa referencia fuerte dentro de mi bloque?

Desde la sesión de la WWDC, entiendo que hacer referencia a ivars en un bloque realmente está creando una referencia al yo implícito que estos ivars cuelgan.

Para mí, esto implica que realmente no hay ningún caso simple o trivial en el que sea correcto acceder a ivars en un bloque sin la danza débil / fuerte para asegurar que no haya ciclos. ¿O estoy leyendo demasiado en un caso de esquina que no se aplica a casos simples, como mi ejemplo?

- (void)openIrisAnimated:(BOOL)animated { if (_isIrisOpened) { NSLog(@"Asked to open an already open iris."); return; // Bail } // Put the common work into a block. // Note: “_topView” and “_bottomView” are the backing ivars of // properties “topView” and “bottomView” void (^openIris)() = ^{ _topView.frame = CGRectMake(....); _bottomView.frame = CGRectMake(....); }; // Now do the actual opening of the iris, whether animated or not: if (animated) { [UIView animateWithDuration:0.70f animations:^{ openIris(); }]; } else { openIris(); } _irisOpened = YES; // Because we have now just opened it }

Así es como volvería a escribir la pieza de bloque de openIris usando la guía de la Sesión # 322, pero me pregunto si todos mis bloques similares requieren esta danza de referencia débil / fuerte para garantizar la corrección y la estabilidad:

__weak MyClass *weakSelf = self; void (^openIris)() = ^{ MyClass *strongSelf = weakSelf; if (strongSelf) { strongSelf.topView.frame = CGRectMake(....); strongSelf.bottomView.frame = CGRectMake(....); } };

¿Es esto de hecho necesario?


El caso de qué preocuparse es algo como addObserverForName:object:queue:usingBlock: Los documentos dicen: "El bloque es copiado por el centro de notificaciones". Bajo ARC, esa palabra "copiar" es una bandera roja; ahora debe seguir los pasos para que usted (la persona que llama) no se escape.

EDITAR: También, a veces ARC en sí lo alertará. El bloque de finalización de -[UIPageViewController setViewControllers:direction:animated:completion:] es un ejemplo de ello. Nunca hubiera sospechado que usar self aquí podría causar un ciclo de retención, pero ARC advirtió que lo haría, así que hice la danza débil-fuerte por si acaso.


Solo hay un ciclo aquí si el yo luego mantiene una referencia al bloque (o algo que es de uno mismo). Si no es así, es bueno ir ya que la vida útil del bloque no está dictada por el yo que retuvo.

Entonces, en tu ejemplo particular, pareces estar claro. Los bloques de animación no necesitan participar en la auto danza débil / fuerte.