2011-10-13 124 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]]; 
} 

此塊移動到堆上,並且應該解決您的問題。