Block內(nèi)的強(qiáng)引用

眾所周知,當(dāng)某個(gè)對象持有著一個(gè)Block的時(shí)候,如果在Block內(nèi)部使用強(qiáng)引用反過來持有這個(gè)對象,就會(huì)導(dǎo)致引用循環(huán)。為了避免引用循環(huán),可以使用__weak修飾符,蘋果的官方文檔在用代碼演示__weak修飾符的時(shí)候,有這么一個(gè)例子:



  那么,myController持有著completionHander,在completionHander內(nèi)部又用一個(gè)strongMyController反過來去持有myController,這不也是一個(gè)引用循環(huán)嗎?為了探究這個(gè)問題,可以用下面的方法來測試一下:

1、編寫一個(gè)類ViewController,然后在類內(nèi)編寫方法test,做一個(gè)疑似的引用循環(huán):



2、然后通過一個(gè)clang命令將這個(gè)類轉(zhuǎn)換成C語言代碼:

clang -x objective-c -rewrite-objc -isysroot
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk
-fobjc-arc -stdlib=libc++ -mmacosx-version-min=10.7 -fobjc-runtime=macosx-10.7
-Wno-deprecated-declarations ViewController.m

3、由此可以得到一個(gè)cpp文件,將文件中主要的部分提取出來如下:



4、可以發(fā)現(xiàn):

  • 在Block結(jié)構(gòu)體中看到,被Block捕獲的變量是
ViewController *const __weak weakSelf;

所以Block本身對self的引用仍然只是弱引用,并不造成引用循環(huán)。

  • strongSelf只存在于Block對應(yīng)的函數(shù)__ViewController__test_block_func_0里,它的生命周期只在這個(gè)函數(shù)執(zhí)行的過程中,函數(shù)執(zhí)行前它不會(huì)存在,函數(shù)執(zhí)行完它立刻就被釋放了。
  • 所以:
    ①、如果函數(shù)執(zhí)行前self變?yōu)閚il了,那么函數(shù)不會(huì)執(zhí)行,沒有任何引用循環(huán)發(fā)生;
    ②、如果函數(shù)執(zhí)行過程中self變?yōu)閚il了,那么函數(shù)一開始聲明的strongSelf會(huì)暫時(shí)持有著self,此時(shí)會(huì)有一個(gè)暫時(shí)的引用循環(huán)。當(dāng)函數(shù)執(zhí)行完(即是Block執(zhí)行完),strongSelf超出作用域被釋放,引用循環(huán)從這里開始打破。接下來,由于沒有任何強(qiáng)引用持有self了,于是self被釋放,最后Block也因?yàn)闆]有任何強(qiáng)引用持有它也被釋放了。所有對象就都被順利釋放了。

所以最終可以確定:蘋果的演示代碼有可能會(huì)造成引用循環(huán),但是只是一個(gè)暫時(shí)的、可以被打破的引用循環(huán),不會(huì)導(dǎo)致內(nèi)存泄漏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容