2011-12-02 9 views
9

Ok, por lo que entiendo cómo evitar self conservan ciclos con bloques, ¿qué hay de los casos cuando envío un mensaje a sí mismo a partir de un método dentro de un bloque anidado más profundo en la pila de llamadas de esta manera:Bloques y lo propio de lo denominado método

- (void)methodA { 
    __block MyClass *blockSelf = self; 
    [someObject block:^{ 
     [blockSelf methodB]; 
    }]; 
} 

- (void)methodB { 
    ... 
    [self methodC]; 
    ... 
} 

- (void)methodC { 
} 

En este caso [blockSelf methodB] está bien, pero está enviando [self methodC] desde methodB provocando el ciclo de retención o no? No se puede encontrar la respuesta en ninguna parte ...

Respuesta

8

No hay ciclo de retención allí. Cuando se define un literal de bloque dentro de un método, el contexto que puede ser capturado por el bloque se limita a lo que es visible dentro de ese método. En su ejemplo:

- (void)methodA { 
    __block MyClass *blockSelf = self; 
    [someObject block:^{ 
     [blockSelf methodB]; 
    }]; 
} 

el bloque literal, a saber:

^{ 
    [blockSelf methodB]; 
} 

es capaz de ver lo siguiente:

  1. self y _cmd, que están ocultos parámetros disponibles en cada Objetivo -C método. Si -methodA tuviera parámetros formales, la literal del bloque también podría verlos;
  2. Cualquier variable de ámbito de bloque dentro del bloque función/método, es decir, cada variable local dentro del método y que es visible en el punto donde se define el literal del bloque. En el ejemplo, la única variable local dentro de -methodA es blockSelf que, debido a que es __block -calificado, no se retiene;
  3. Cualquier variable de ámbito de archivo (también conocido como variables globales).

Un literal de bloque no es consciente (y, en el caso general, no puede ser consciente) de lo que sucede dentro de otras funciones/métodos, por lo tanto cualquier contexto disponible dentro llamado funciones/métodos no es capturado por el literal Bloque. Solo necesita preocuparse por el método donde se define el literal del bloque.

estoy usando la convención de Apple de capitalizar bloque cuando se refiere a dispositivos de cierre/lambdas (es decir, ^{}) y el bloque de minúscula cuando se refiere a bloques C (es decir, {}).

+0

Cool, gracias! Esto eliminaría un montón de feos "hacks de parámetros" de mis métodos de ayuda ... – Tom

+0

"No hay ningún ciclo de retención allí". bien, depende de qué 'someObject' es y si conserva el bloque pasado a él. Si 'self' conserva' someObject' (es decir, es una variable de instancia), y si 'someObject' almacena y conserva el bloque pasado a' block: ', entonces habría un ciclo de retención. – newacct

Cuestiones relacionadas