2013-11-26 97 views
0

說明釋放塊:如何使用ARC

我我的塊傳遞給異步方法,而當操作結束的叫法。我想拒絕在操作完成前調用該塊。但是,如果我在我的類中爲塊變量指定nil,則無論如何都會調用它。我調試它,我看到,如果我分配nil來阻止變量1變量2在沒有零。下面的代碼說明了它:

void (^d1)(NSArray *data) = ^(NSArray *data) {}; 

void (__weak^d2)(NSArray *data) = d1; 

d1 = nil; 

輸出

(lldb) po d1 
<__NSGlobalBlock__: 0x9c22b8>] 
(lldb) po d2 
<__NSGlobalBlock__: 0x9c22b8> 
(lldb) po d1 
<nil> 
(lldb) po d2 
<__NSGlobalBlock__: 0x9c22b8> 

問題

爲什麼塊D2不是零?是否按值複製,不作爲指針複製?

回答

5

首先,你永遠不應該依賴於某個對象在特定的地方被釋放。其他人(例如自動釋放池)始終可能在您不知情的情況下持有對其的引用。一個對象在任何地方都不會被釋放是沒有錯的。

好的,您的情況:__NSGlobalBlock__給出了一個提示:這是一個「全局塊」。在當前塊的實現中,有三種類型的塊對象:堆棧塊(__NSStackBlock__),堆塊(__NSMallocBlock__)和全局塊(__NSGlobalBlock__)。

塊是封閉(即使用一些局部變量從外範圍)開始作爲「堆棧塊」 - 對象結構具有自動存儲持續時間,就像一個局部變量,並且變得無效時它會離開它定義的範圍。當一個堆棧塊被「複製」時,它會像堆棧中的所有其他對象一樣被移動到堆上的一個動態分配對象中。這是一個堆塊。它像Cocoa中的其他對象一樣被引用計數,並且複製它與保留效果相同。

不是關閉(這是你的例子中的塊)實現爲「全局塊」的塊。因爲它不包含任何捕獲的變量,所以塊的所有實例都是相同的,因此在整個程序中只有一個實例。它像字符串文字一樣被靜態分配,並且在程序的整個生命週期內都存在。它沒有引用計數,保留,釋放和複製它沒有任何作用。它不能被釋放;這就是爲什麼你的弱引用永遠不會被設置爲nil。如果指向的對象被取消分配,則僅參考__weak參考將被設置爲nil

+0

很好的答案,謝謝。 –

1

d1是對您創建的塊的引用,^(NSArray *data) {};。一旦將d2分配給d1的參考,該塊上的參考計數就會增加。當你將d1設置爲零時,仍然有一個強大的指向塊d2的指針。

+0

謝謝,你的回答很有用。我已將__weak添加到第二個指針(問題已更新)。爲什麼現在阻止d2不爲空? –

+0

非常有趣。可能與ARC有關......編譯器魔法喜歡將自己納入這類問題。我猜在本地作用域中的塊聲明會自動複製到堆中,而不管指針強度如何,直到超出範圍纔會被釋放。那是我在黑暗中的鏡頭。 – John