__weak
本身是可以避免循環引用的問題的,但是其會導致外部對象釋放了之后,block 內部也訪問不到這個對象的問題,我們可以通過在 block 內部聲明一個 __strong
的變量來指向 Obj,使外部對象既能在 block 內部保持住,又能避免循環引用的問題。
__block
本身無法避免循環引用的問題,但是我們可以通過在 block 內部手動把 blockObj 賦值為 nil 的方式來避免循環引用的問題。另外一點就是__block
修飾的變量在 block 內外都是唯一的,要注意這個特性可能帶來的隱患。
總結:
1 . 在MRC(手動內存計數)模式下,__block
修飾,可以避免循環引用;ARC(自動內存計數)模式下,__block
修飾,還是會引起循環引用問題;
2 . __block
不管是ARC還是MRC模式下都可以使用,可以修飾對象,還可以修飾基本數據類型;
3 . __weak
只能在ARC模式下使用,也只能修飾對象,不能修飾基本數據類型;
4 . __block
對象可以在block中被重新賦值,__weak
不可以;
API Reference對__block變量修飾符的解釋,大概意思:
1.__block對象在block中是可以被修改、重新賦值的。
2.__block對象在block中不會被block強引用一次,從而不會出現循環引用問題。
API Reference對__weak變量修飾符的解釋,大概意思:
使用了__weak修飾符的對象,作用等同于定義為weak的property。自然不會導致循環引用問題,因為蘋果文檔已經說的很清楚,當原對象沒有任何強引用的時候,弱引用指針也會被設置為nil。
因此,__block和__weak修飾符的區別其實是挺明顯的:
1.__block不管是ARC還是MRC模式下都可以使用,可以修飾對象,還可以修飾基本數據類型。
2.__weak只能在ARC模式下使用,也只能修飾對象(NSString),不能修飾基本數據類型(int)。
3.__block對象可以在block中被重新賦值,__weak不可以。
Tips:__unsafe_unretained修飾符可以被視為iOS SDK 4.3以前版本的__weak的替代品,不過不會被自動置空為nil。所以盡可能不要使用這個修飾符。
Block的生命周期管理非常的微妙,與ARC混在一起后,更加復雜。
當Block延stack向上(up)傳遞的時候,直接返回,編譯器會添加[[ copy] autorelease]代碼。
當Block延stack向下傳遞給需要retain的容器的時候,需要顯式的調用[^{} copy]方法。
在ARC下,__block修改的NSObject指針依然會被retain。
在ARC下,一個block內引用一個對象的實例變量后,self會被retain,所以極易造成strong reference cycle,可以通過__weak指針來避免這種情形,因為ARC不會為__weak指針retain。