2014-02-25 56 views
2

所以,即時嘗試在數組中建立一個塊隊列,然後在稍後階段執行隊列,隊列在forloop中構建,該forloop使用枚舉在塊中使用的字符串。通過快速枚舉在for循環中使用塊的缺陷

NSArray *array = @[@"test", @"if", @"this", @"works"]; 
NSMutableArray *queue = [NSMutableArray new]; 

for(id key in array){ 

    //add the work to the queue 
    void (^ request)() = ^{ 
     NSLog(@"%@", key); 
    }; 

    [queue addObject:request]; 
    //request(); //this works fine if i just execute the block here, all the strings are printed 
} 

for(id block in queue){ 

    void (^ request)() = block; 

    request(); //this just prints 'works' multiple times instead of all the other strings 
} 

做塊不能在for循環與枚舉對象的工作(當不在同一個for循環執行),或者這也似乎是一個錯誤嗎?

+1

打開ARC,這不會發生。 –

+0

是的,我們正在將應用程序轉換爲弧形,但它是一個整體項目,所以不那麼容易。我應該在這個問題中提到,我的壞 – Fonix

+0

@JoshCaswell:「這不會發生。」從我對ARC規範的閱讀中,我不能保證。 – newacct

回答

5

變化

[queue addObject:request]; 

[queue addObject:[request copy]]; 

UPDATE: 塊在堆棧中創建。所以request是一個局部變量。當你將它添加到NSMutableArray時,它會被保留,但對於塊來說是不夠的!無論如何,當你離開{}時,Block會被刪除 - 保留與否都無關緊要。您應該先將它複製到堆中,然後保留(通過添加到數組中)。

+0

謝謝,這個技巧,我很快就接受了答案 – Fonix

+2

應該注意的是,當第二個代碼執行時,初始代碼不會複製堆棧的好東西(意味着您在塊中使用的所有變量),因此您的塊是所有引用的一些addr碰巧是@「works」 – DanZimm

+2

@DanZimm實際上塊沒有複製密鑰,它只是留在堆棧上。複製消息需要將其從堆棧移動到堆。它僅僅因爲他足夠幸運而能夠打印'works',所以該塊的最後一個實例在堆棧中仍然完整無缺,並且可以執行。 –