2011-10-13 27 views
6

Considere el siguiente fragmento de código:bloques, bucles y variables locales

for(/* some condition */) { 
    int x = rand(); 
    [array addObject:^(){ 
     NSLog(@"%d", x); 
    }] 
} 

for(void (^block)() in array) { 
    block(); 
} 

Ahora me esperaría este fragmento de código para imprimir todos los valores asignados a x en ese bucle; sin embargo, parece que todos los bloques comparten la misma variable 'x' (presumiblemente la última).

¿Alguna idea de por qué esto es así y cómo podría arreglar el código para que cada bloque contenga la variable 'x' tal como era en el momento en que se definió el bloque?

+0

Todavía estoy aprendiendo bloques, pero me viene a la mente una cosa extraña. Cuando agrega addObject :, la matriz retendrá por defecto el objeto de bloque. Sin embargo, los objetos de bloque se ponen en la pila cuando se declaran, por lo que parece que de inmediato quedarían fuera del alcance. Block_Copy movería el bloque al montón que parece ser lo correcto. –

Respuesta

7

La documentación específicamente says not to do this. La razón es que los bloques se asignan en la pila, lo que significa que pueden salir del alcance. Por el mismo motivo, no puede acceder a la variable x fuera del primer bucle for, tampoco debe usar ese bloque. x ha salido del alcance, junto con el bloque en sí, y podría contener cualquier valor.

Para evitar esto, se puede tomar una copia del bloque de este modo:

for(/* some condition */) { 
    int x = rand(); 
    void(^logBlock)() = ^() { NSLog(@"%d", x); } 
    [array addObject:[[logBlock copy] autorelease]]; 
} 

Esto mueve el bloque en el montón, y debería solucionar su problema.

Cuestiones relacionadas