Bloquea y retiene ciclos

Una pregunta menor: ¿por qué Xcode se queja de que el listing 1 llevaría a un ciclo de retención, mientras que en el listing 2 no? En ambos casos _clients es una variable de instancia int . En el listing 2 se le asigna 0 en el método init .

Información de background: Me gustaría ejecutar el bucle en el bloque, siempre que al less un cliente solicite actualizaciones del acelerómetro del iPhone, que estoy publicando en un canal de networkingis. Si ya no quedan más clientes, el ciclo abandonaría y dejaría de publicar los datos del acelerómetro.

Listing 2 proviene de una pequeña aplicación de testing que escribí para verificar que mi idea funcione. Listing 1 se implementa en el proyecto real.

Listado 1

 - (id)init { self = [super init]; if (self) { _clients = 0; /** * The callback being executed */ _callback = ^ { while (_clients > 0) { // Capturing 'self' strongly in this block is likely to lead to a retain cycle NSLog(@"Publish accelerometer data to networkingis (connected clients: %d)", _clients); } }; } return self; } 

Listado 2

 - (void)touchedConnectButton:(id)sender { _clients += 1; dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(concurrentQueue, ^() { while(_clients > 0) { NSLog(@"Connected clients: %d", _clients); } }); } 

En ambos listdos, te refieres a una variable de instancia, capturándote implícitamente a ti mismo. Un fuerte yo

Esto lleva a una primera solución a su problema:

 int clients = _clients; // use `clients` instead of `_clients` in your blocks 

Alternativamente, puedes usar un yo débil:

 id __weak weakself = self; // use `weakself->_clients` in your blocks 

La razón por la que obtuvo el error en el listdo 1 es porque el bloque se captura a sí mismo y el bloque se almacena en una variable de instancia del mismo yo, lo que lleva a un ciclo de retención. Ambas soluciones anteriores resolverán ese problema.

Hay un ciclo de retenciones en el Listado 1 porque en el Listado1 self retiene el ivar _callback en el que accedes a otro ivar, _clients, y porque _clients es una var primitiva, el bloque se retiene para acceder a él.

En Listing2, el bloque es retenido por la queue y no por sí mismo.