Блоки, циклы и локальные переменные - PullRequest
6 голосов
/ 13 октября 2011

Рассмотрим следующий фрагмент кода:

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

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

Теперь я ожидаю, что этот фрагмент кода распечатает все значения, присвоенные x в цикле for; однако кажется, что все блоки имеют одну и ту же переменную 'x' (предположительно, последний).

Есть идеи, почему это так, и как я могу исправить код, чтобы каждый блок содержал переменную 'x', как это было во время определения блока?

1 Ответ

7 голосов
/ 13 октября 2011

В документации, в частности говорится, не делать этого . Причина в том, что блоки размещаются в стеке , что означает, что они могут выходить за рамки. По той же причине, по которой вы не можете получить доступ к переменной x вне первого цикла for, вы также не должны использовать этот блок. x вышел из области видимости вместе с самим блоком и может содержать любое значение.

Чтобы обойти это, вы можете взять копию блока следующим образом:

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

Это перемещает блок в кучу и должно решить вашу проблему.

...