2011-10-13 7 views
6

は、次のコードを考えてみましょう:ブロック、ループやローカル変数

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

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

今私は、このコードスニペットは、ループのためにその中のxに割り当てられたすべての値をプリントアウトすることを期待します。しかし、すべてのブロックが同じ 'x'変数(おそらく最後の変数)を共有しているようです。

これはなぜそうであり、ブロックが定義されたときのように各ブロックに変数 'x'が含まれるようにコードを修正することができますか?

+0

私はまだブロックを自分で学習していますが、ここでは奇妙なことが一つあります。 addObject:を実行すると、配列はデフォルトでブロックオブジェクトを保持します。しかし、ブロックオブジェクトは宣言されたときにスタックに置かれるため、ここではすぐに範囲外になるように見えます。 Block_Copyはブロックをヒープに移動します。このヒープは正しいことのようです。 –

答えて

7

具体的にはsays not to do thisです。その理由は、ブロックがブロックにスタックに割り当てられているため、スコープから外れる可能性があるからです。同じ理由で、最初のforループの外側にある変数xにアクセスできないため、そのブロックを使用しないでください。 xは、ブロック自体とともにスコープ外になり、任意の値を含むことができます。この問題を回避するには

、あなたはそうのようなブロックのコピーをとることができます。

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

これは、ヒープ上にブロックを移動させ、あなたの問題を解決する必要があります。

関連する問題