recursividad programacion ejemplos ios objective-c automatic-ref-counting objective-c-blocks

ios - programacion - Bloqueo de recursión de bloque y rotura.



recursividad java (2)

Creo que @newacct tiene razón sobre la solución de @Matt Wilding; Parece que nada tendrá una referencia fuerte al siguiente bloque en ese caso y dará lugar a una excepción de tiempo de ejecución cuando se ejecute (al menos lo hizo para mí).

No sé qué tan común es encontrar bloques llamados recursivamente en la naturaleza en objc. Sin embargo, en una implementación en el mundo real (si realmente se requiere), por ejemplo, en un controlador de vista, se podría definir el bloque y luego configurar una propiedad de interfaz interna con una referencia sólida a dicho bloque:

typedef void(^PushButtonBlock)(); @interface ViewController () @property (strong, nonatomic) PushButtonBlock pushButton; @end @implementation ViewController ... // (in viewDidLoad or some such) __weak ViewController *weakSelf = self; self.pushButton = ^() { [weakSelf.button pushIt]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), weakSelf.pushButton); }; self.pushButton(); ... @end

Esto funciona bien para mí y no tiene advertencias del compilador sobre los ciclos de retención (y no hay fugas en los instrumentos). Pero, creo que probablemente evitaría hacer esto (llamadas de bloque recursivas) en la mayoría de los casos en el objc: huele mal. Pero interesante en cualquier caso.

Para ilustrar mejor la pregunta, considere la siguiente forma simplificada de recursión de bloques:

__block void (^next)(int) = ^(int index) { if (index == 3) { return; } int i = index; next(++i); }; next(0);

XCode (habilitado para ARC) advierte que " Capturar fuertemente el ''siguiente'' en este bloque puede conducir a un ciclo de retención ".

Convenido.

Pregunta 1 : ¿Se rompería con éxito el ciclo de retención al establecer el bloque en nil , de esta manera?

__block void (^next)(int) = ^(int index) { if (index == 3) { next = nil; // break the retain cycle return; } int i = index; next(++i); }; next(0);

(Nota: seguirías recibiendo la misma advertencia, pero quizás no esté justificada)

Pregunta 2 : ¿Qué sería una mejor implementación de la recursión en bloque?

Gracias.


Para lograr la ejecución del bloque recursivo sin ciclo de retención, necesita usar dos referencias de bloque, una débil y otra fuerte. Entonces, para tu caso, este es el aspecto que podría tener el código:

__block __weak void (^weak_next)(int); void (^next)(int); weak_next = next = ^(int index) { if (index == 3) { return; } int i = index; weak_next(++i); }; next(0);

Tenga en cuenta que el bloque captura la referencia del bloque débil (weak_next), y el contexto externo captura la referencia fuerte (siguiente) para mantener el bloque alrededor. Ambas referencias apuntan al mismo bloque.

Consulte https://.com/a/19905407/1956124 para ver otro ejemplo de este patrón, que también utiliza la recursión de bloques. Además, la discusión en la sección de comentarios del siguiente artículo también es relevante aquí: http://ddeville.me/2011/10/recursive-blocks-objc/