68

我讀Xcode的文件,這裏的東西,我感到困惑:__weak和__block引用有什麼區別?

__block typeof(self) tmpSelf = self; 
[self methodThatTakesABlock:^ { 
    [tmpSelf doSomething]; 
}]; 

以下是從文檔複製:

塊形式的強引用它捕獲變量。如果在塊中使用 self,則該塊形成對self的強參考,因此如果 self也對該塊(其通常爲 所做的那樣)有強烈的參考,則會產生強的參考循環。爲避免此循環,您需要 在上面的示例中爲 創建對塊外部自我的弱引用(或__block)。

我不明白'弱(或__block)'是什麼意思?

__block typeof(self) tmpSelf = self; 

__weak typeof(self) tmpSelf = self; 

完全這裏同樣

我發現了另一塊在文件中:

注意:在收集垃圾環境,如果你同時申請__weak__block修飾符到一個變量,然後塊不會確保它保持活着。

所以,我完全不解。

回答

99

大約從__block在存儲的文檔

__block變量住在所述變量的詞法作用域和所有塊,並宣佈或變量的詞法範圍內創建的塊拷貝之間共享。因此,如果在幀中聲明的塊的任何副本存活超過幀的末尾(例如,通過在某處等待以後執行),那麼存儲器將在存儲器堆棧幀的銷燬中倖存下來。給定詞法範圍中的多個塊可以同時使用共享變量。

從約__weak

__weak的文檔指定了不保持引用的對象活着的參考。當沒有強引用時,弱引用設置爲零。

所以他們在技術上是不同的東西。 __block將停止將您的外部作用域中的變量複製到塊作用域中。 __weak是一個自我劃定的弱指針。

注意我在技術上說,因爲你的情況他們會做(幾乎)相同的事情。唯一的區別是如果你使用ARC或不。如果您的項目使用ARC並且僅適用於iOS4.3及更高版本,請使用__weak。它確保如果全局範圍引用以某種方式發佈,則引用設置爲nil。如果您的項目不使用ARC或者適用於較舊的操作系統版本,請使用__block。

這裏有一個微妙的區別,請確保你理解它。

編輯:另一個難題是__unsafe_unretained。該修飾符與__weak幾乎相同,但是對於4.3之前的運行時環境。但是,它不會被設置爲零,並且可能會讓您掛起指針。

+0

很清楚,謝謝。 – HanXu 2012-08-02 12:59:28

+1

這是否仍適用於使用ARC的iOS7?我運行了一個分析器,我發現我的控制器正在釋放,即使我沒有在塊中使用__block或__weak並引用self。 – 2014-08-13 06:06:29

+0

對於想要查看文檔的人:https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html,https://developer.apple.com/library/ios /documentation/Cocoa/Conceptual/Blocks/Articles/bxVariables.html – 2015-01-27 05:52:32

5

在手動引用計數模式下,__block id x;具有不保留x的效果。在ARC模式下,__block id x;默認保留x(就像所有其他值一樣)。要在ARC下獲得手動引用計數模式行爲,可以使用__unsafe_unretained __block id x ;.正如名字__unsafe_unretained意味着,但是,有一個非保留的變量是危險的(因爲它可以晃),因此不鼓勵。兩個更好的選擇是使用__weak(如果您不需要支持iOS 4或OS X v10.6),或者將__block值設置爲零以中斷保留週期。

apple docs

0

除了在__block VS __weak其他的答案,還有另一種方式,以避免在方案中保留週期。

@weakify(self); 
[self methodThatTakesABlock:^ { 
    @strongify(self); 
    [self doSomething]; 
}]; 

More Info about @Weakify @Strongify Marco