Block 的迴圈引用

2022-02-16 04:44:53 字數 2249 閱讀 6216

block是在棧上生成的,所以一般使用copy方法把block複製到堆上,避免block被立刻釋放。

block會對內部的變數形成強引用,而如果同時該變數又持有這個block,就會導致迴圈引用而無法釋放,從而導致記憶體洩露。

最常見的就是self持有block,而又在block內部呼叫self的方法或屬性,那selfblock就會形成迴圈引用而無法釋放。由於我們習慣在dealloc中釋放物件,但是即使在dealloc中將block釋放也沒用,因為selfdealloc根本不會跑進去。比如:

1 self.myblock = ^void

();

其實,最簡單的解決方法就是在self的某個非dealloc方法中將block主動釋放,並在需要釋放self之前呼叫這個方法,這樣才能有效的解除引用。但是這種方法使用起來比較麻煩,而且很容易忘記呼叫。

所以我們一般是在block中使用弱引用的self。下面分別介紹arcmrc中在block中使用弱引用self的方法。

1 __weak typeof(self) weakself =self;

23 self.myblock = ^void

();

這樣做的好處是不必在block直接使用self,這樣就不會對self進行強引用,只要self需要釋放,self就會自動釋放,block也會自動釋放。在arc中,進入block前,需要使用__weakself進行弱引用,並在block中使用__strongweakself進行強引用。

這樣做的另乙個好處是,在arc中使用__weak之後,如果self在某個地方被釋放了,那weakself也會被自動置為nil,這樣即使在block中使用weakself,也不會訪問錯誤。

而在block中使用__strong則是為了避免在使用block的過程中self被釋放導致訪問出錯。

1 __block typeof(self) blockself =self;

23 self.myblock = ^void

();

其實,mrc的基本思路和arc是一樣的。有兩處不同:

mrc中使用__block而不是__weak進行弱引用,因為在arc中使用__block會對該物件進行強引用。

mrcblock中使用malloc_zone_from_ptr()方法判斷blockself是否已經被釋放,因為mrc不會對已釋放的物件自動置為nil

可見,無論是mrc還是arc,解決方法都是類似的。雖然block的使用增加了簡潔性和便利性,但使用block的過程中也要時刻注意避免記憶體洩露。

how do i declare a block in objective-c? 總結了宣告block的幾種格式,在開發過程中可以參考使用。

block 迴圈引用

結論 block作為成員變數,內部引用self的成員變數,必須使用self 弱引用 block作為區域性變數,無論怎樣寫,都不會對self造成強引用 block為變數 1 block為成員變數 typedef nsstring blockcc void inte ce twoviewcontroll...

block迴圈引用

底層原始碼 typedef void ghblock void struct main block impl 0 static void main block func 0 struct main block impl 0 cself static void main block copy 0 st...

BLOCK迴圈引用

何時block才會迴圈引用 為什麼block會迴圈引用 我們很多行為會導致block的copy,而當block被copy時,會對block中用到的物件產生強引用 arc下 或者引用計數加一 mrc下 如下 property nonatomic,readwrite,copy completionblo...