Block 的循环引用
Block是在棧上生成的,所以一般使用copy方法把Block復(fù)制到堆上,避免Block被立刻釋放。
Block會(huì)對(duì)內(nèi)部的變量形成強(qiáng)引用,而如果同時(shí)該變量又持有這個(gè)Block,就會(huì)導(dǎo)致循環(huán)引用而無(wú)法釋放,從而導(dǎo)致內(nèi)存泄露。
最常見(jiàn)的就是self持有Block,而又在Block內(nèi)部調(diào)用self的方法或?qū)傩?#xff0c;那self和Block就會(huì)形成循環(huán)引用而無(wú)法釋放。由于我們習(xí)慣在dealloc中釋放對(duì)象,但是即使在dealloc中將Block釋放也沒(méi)用,因?yàn)閟elf的dealloc根本不會(huì)跑進(jìn)去。比如:
1 self.MyBlock = ^void(){ 2 3 [self doSomething]; 4 };?
其實(shí),最簡(jiǎn)單的解決方法就是在self的某個(gè)非dealloc方法中將Block主動(dòng)釋放,并在需要釋放self之前調(diào)用這個(gè)方法,這樣才能有效的解除引用。但是這種方法使用起來(lái)比較麻煩,而且很容易忘記調(diào)用。
所以我們一般是在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,這樣就不會(huì)對(duì)self進(jìn)行強(qiáng)引用,只要self需要釋放,self就會(huì)自動(dòng)釋放,Block也會(huì)自動(dòng)釋放。在ARC中,進(jìn)入Block前,需要使用__weak對(duì)self進(jìn)行弱引用,并在Block中使用__strong對(duì)weakSelf進(jìn)行強(qiáng)引用。
這樣做的另一個(gè)好處是,在ARC中使用__weak之后,如果self在某個(gè)地方被釋放了,那weakSelf也會(huì)被自動(dòng)置為nil,這樣即使在Block中使用weakSelf,也不會(huì)訪問(wèn)錯(cuò)誤。
而在Block中使用__strong則是為了避免在使用Block的過(guò)程中self被釋放導(dǎo)致訪問(wèn)出錯(cuò)。
?
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 };
其實(shí),MRC的基本思路和ARC是一樣的。有兩處不同:
在MRC中使用__block而不是__weak進(jìn)行弱引用,因?yàn)樵贏RC中使用__block會(huì)對(duì)該對(duì)象進(jìn)行強(qiáng)引用。
在MRC的Block中使用malloc_zone_from_ptr()方法判斷blockSelf是否已經(jīng)被釋放,因?yàn)镸RC不會(huì)對(duì)已釋放的對(duì)象自動(dòng)置為nil。
?
可見(jiàn),無(wú)論是MRC還是ARC,解決方法都是類(lèi)似的。雖然Block的使用增加了簡(jiǎn)潔性和便利性,但使用Block的過(guò)程中也要時(shí)刻注意避免內(nèi)存泄露。
How Do I Declare A Block in Objective-C??總結(jié)了聲明Block的幾種格式,在開(kāi)發(fā)過(guò)程中可以參考使用。
?
轉(zhuǎn)載于:https://www.cnblogs.com/coltfoal/p/4763540.html
總結(jié)
以上是生活随笔為你收集整理的Block 的循环引用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: [LeetCode]#13 3sum
- 下一篇: plsql与64位的Oracle关联方法