Block 的循环引用
Block是在棧上生成的,所以一般使用copy方法把Block復制到堆上,避免Block被立刻釋放。
Block會對內部的變量形成強引用,而如果同時該變量又持有這個Block,就會導致循環引用而無法釋放,從而導致內存泄露。
最常見的就是self持有Block,而又在Block內部調用self的方法或屬性,那self和Block就會形成循環引用而無法釋放。由于我們習慣在dealloc中釋放對象,但是即使在dealloc中將Block釋放也沒用,因為self的dealloc根本不會跑進去。比如:
1 self.MyBlock = ^void(){ 2 3 [self doSomething]; 4 };?
其實,最簡單的解決方法就是在self的某個非dealloc方法中將Block主動釋放,并在需要釋放self之前調用這個方法,這樣才能有效的解除引用。但是這種方法使用起來比較麻煩,而且很容易忘記調用。
所以我們一般是在Block中使用弱引用的self。下面分別介紹ARC和MRC中在Block中使用弱引用self的方法。
ARC
1 __weak typeof(self) weakSelf = self; 2 3 self.MyBlock = ^void(){ 4 5 __strong typeof(self) strongSelf = weakSelf; 6 7 [strongSelf doSomething]; 8 };這樣做的好處是不必在Block直接使用self,這樣就不會對self進行強引用,只要self需要釋放,self就會自動釋放,Block也會自動釋放。在ARC中,進入Block前,需要使用__weak對self進行弱引用,并在Block中使用__strong對weakSelf進行強引用。
這樣做的另一個好處是,在ARC中使用__weak之后,如果self在某個地方被釋放了,那weakSelf也會被自動置為nil,這樣即使在Block中使用weakSelf,也不會訪問錯誤。
而在Block中使用__strong則是為了避免在使用Block的過程中self被釋放導致訪問出錯。
?
MRC
1 __block typeof(self) blockSelf = self; 2 3 self.MyBlock = ^void(){ 4 5 if (!malloc_zone_from_ptr(blockSelf)) 6 return; 7 8 __strong typeof(self) strongSelf = blockSelf; 9 10 [strongSelf doSomething]; 11 };
其實,MRC的基本思路和ARC是一樣的。有兩處不同:
在MRC中使用__block而不是__weak進行弱引用,因為在ARC中使用__block會對該對象進行強引用。
在MRC的Block中使用malloc_zone_from_ptr()方法判斷blockSelf是否已經被釋放,因為MRC不會對已釋放的對象自動置為nil。
?
可見,無論是MRC還是ARC,解決方法都是類似的。雖然Block的使用增加了簡潔性和便利性,但使用Block的過程中也要時刻注意避免內存泄露。
How Do I Declare A Block in Objective-C??總結了聲明Block的幾種格式,在開發過程中可以參考使用。
?
轉載于:https://www.cnblogs.com/coltfoal/p/4763540.html
總結
以上是生活随笔為你收集整理的Block 的循环引用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [LeetCode]#13 3sum
- 下一篇: plsql与64位的Oracle关联方法