2015-03-19 41 views
1
-(id)getBlockArray 
{ 
    int val = 10; 

    return [[NSArray alloc] initWithObjects:^{NSLog(@"1-%d",val);},^{NSLog(@"2-%d",val);} ,^{NSLog(@"3-");}, nil]; 
} 
+0

id obj = [self getBlockArray]; NSLog(@「%@」,obj); 的日誌(看,它們是不同的,我想知道爲什麼嗎?): 2015年3月19日14:39:26.968 BTLE傳輸[28037:3241024( 「<__ NSMallocBlock__:0x7ffeb3d9b940>」, 「<__ NSStackBlock__ :0x7fff55da7bf0>「, 」<__ NSGlobalBlock__:0x109e5d120>「 ) – user2223542 2015-03-19 07:11:51

+2

請編輯您的問題。通常不需要評論您的問題以添加信息。添加一個對帖子完整句子的問題。標題有一個問號,但沒有明確說明您的問題。 – Anthon 2015-03-19 07:19:12

回答

2

不捕獲任何變量的塊是全局塊。由於該塊的所有實例都是相同的,因此編譯器可以爲程序的生命週期靜態分配一個副本。

捕獲變量(閉包)的塊是堆棧或堆(malloc)塊。塊從堆棧開始,作爲堆棧塊。當堆棧塊第一次被複制時,它將被移動到堆中。複製堆塊不會創建另一個副本;但只是保留它。

第三個是全局塊是顯而易見的,因爲它沒有捕獲任何變量。前兩個捕獲變量。顯然,第一個是複製的,第二個不是。

ARC規範不保證複製前兩個塊中的任何一個。但是,ARC編譯器可以根據需要插入其他副本。 (複製塊不能傷害。)

我相信當Clang ARC編譯器的當前版本在將塊指針類型的表達式傳遞給非塊對象指針類型的參數時會保守地插入副本。這是一個好主意,因爲採用非塊對象指針的API通常只在需要存儲它們時才保留它們,而不是根據塊所需進行復制。事先複製它們可以防止這種情況的不安全。這解釋了第一個參數的複製。第二個呢?我的猜測是,這是因爲它是可變參數而不是明確的參數(-[NSArray initWithObjects:]需要一個參數,類型爲id,然後有可變參數,...),並且Clang關於複製時的規則可能不適用於可變參數(因爲它不知道「參數類型」)。

在將塊傳遞給採用普通對象指針並存儲它們的API(如-[NSArray initWithObjects:])之前,您應該始終複製塊,因爲不能保證複製。

相關問題