block 嵌套中的循環(huán)引用問(wèn)題

引言

相信大家對(duì)block的使用都不會(huì)感到陌生, __weak__strong也成為了大家解決循環(huán)引用的利器. 不過(guò)大家有否想過(guò), block出現(xiàn)嵌套情況時(shí), __weak__strong還能好使嗎, 或者說(shuō)會(huì)不會(huì)有一些需要注意的地方呢?

正篇

首先我們定義了一個(gè)Person類(lèi), .h中只有1個(gè)無(wú)參無(wú)返回的block屬性 -> personBlock, 并且重寫(xiě)了dealloc方法, 如下圖所示:

1.png

2.png

接下來(lái)我們?cè)谥鞣椒ㄖ袆?chuàng)建一個(gè)Person對(duì)象, 由于沒(méi)有把對(duì)象強(qiáng)引用起來(lái), 所以對(duì)象一創(chuàng)建出來(lái)就被釋放了:

3.png

接著我們對(duì)對(duì)象進(jìn)行會(huì)造成循環(huán)引用的操作. 由于對(duì)象強(qiáng)引用著block, block也強(qiáng)引用著對(duì)象, 所以控制臺(tái)并沒(méi)有出現(xiàn)任何的打印, 編譯器也發(fā)出了相應(yīng)的警告:

4.png

為了解決循環(huán)引用問(wèn)題, 我們請(qǐng)出了2大神器__weak__strong, 問(wèn)題當(dāng)然被迎刃而解, 這里的警告只是因?yàn)榻Y(jié)果沒(méi)被使用. 當(dāng)然了, 此處其實(shí)并不需要用到__strong, 但實(shí)際開(kāi)發(fā)中情況復(fù)雜多變, 基于普遍適用性的需求, 此處也用上__strong:

5.png

接下來(lái)主角出場(chǎng)了, 如果block中再次對(duì)block賦值的情況下會(huì)怎么樣呢? 也就是block嵌套. 我們可能會(huì)這樣想, strongPerson已經(jīng)是可以放心使用的對(duì)象了, 還需要擔(dān)心什么循環(huán)引用, 直接套進(jìn)去用就行了. 真是這樣的嗎?

6.png

果然不出所料? 先別開(kāi)心太早, 雖然控制臺(tái)有輸出, 對(duì)象得到了釋放, 可是你有看到編譯器已經(jīng)發(fā)出警告了嗎? 可能你覺(jué)得編譯器出毛病了, 亂警告, 其實(shí)不然, 這里是一個(gè)語(yǔ)法問(wèn)題, 第二層block并沒(méi)有真正被加載進(jìn)內(nèi)存. 什么? 不相信? 我只要加一句代碼問(wèn)題就會(huì)馬上暴露:

7.png

只要在最后把外層的block執(zhí)行一次, 內(nèi)層的block才會(huì)真正地被加載進(jìn)內(nèi)存, 循環(huán)引用問(wèn)題再次出現(xiàn). 出現(xiàn)循環(huán)引用的原因其實(shí)也不難理解, 因?yàn)?code>strongPerson說(shuō)白了也是一個(gè)強(qiáng)引用, 它與一般強(qiáng)引用的區(qū)別在于, 它只會(huì)在被定義的block中對(duì)對(duì)象進(jìn)行強(qiáng)引用, 在block過(guò)后就會(huì)把對(duì)象釋放掉, 所以在第2層block中繼續(xù)用strongPerson出現(xiàn)循環(huán)引用跟一般造成循環(huán)引用的原因其實(shí)是一樣的, 解決方法也是如出一轍, 而且可以繼續(xù)嵌套下去, 此處的警告同樣是結(jié)果沒(méi)被使用:

8.png

補(bǔ)充

另外想補(bǔ)充一個(gè)關(guān)于block強(qiáng)引用對(duì)象的問(wèn)題, 之前在網(wǎng)上看到過(guò)一些說(shuō)法, 大概就是block會(huì)對(duì)內(nèi)部所有的對(duì)象產(chǎn)生一個(gè)強(qiáng)引用, 比如說(shuō):

    self.block = ^{
        self.name = @"Veeco";
    };

這里block首先對(duì)self產(chǎn)生一個(gè)強(qiáng)引用, 其實(shí)還對(duì)name這個(gè)屬性產(chǎn)生了一個(gè)強(qiáng)引用, 在這個(gè)補(bǔ)充里, 我就是想要澄清關(guān)于這個(gè)name屬性被強(qiáng)引用的問(wèn)題.

首先我們?cè)趧偛糯a的基礎(chǔ)上加一個(gè)Dog類(lèi), 只重寫(xiě)其中的dealloc方法:

9.png

接著在Person類(lèi).h中增加一個(gè)Dog屬性 -> dog, 需要注意的是此處用的是weak關(guān)鍵字:

10.png

正篇開(kāi)始, 我們?cè)谥鞣椒ㄖ蟹謩e創(chuàng)建persondog對(duì)象, 并把dog對(duì)象賦值給person對(duì)象的dog屬性, 接著在person對(duì)象的block屬性中訪問(wèn)person對(duì)象的dog屬性, 按照網(wǎng)上的說(shuō)法, 如果block強(qiáng)引用著person對(duì)象的dog屬性的話, 我們是看不到Dog dealloc打印的, 接下來(lái)就來(lái)見(jiàn)證奇跡的時(shí)刻:

11.png

結(jié)果出來(lái)了, Person類(lèi)沒(méi)被釋放這是肯定的, 因?yàn)樵斐闪搜h(huán)引用, 不過(guò)我們看到了Dog dealloc打印, 也就是說(shuō)block并沒(méi)有強(qiáng)引用著person對(duì)象中的dog屬性, 它只強(qiáng)引用著person對(duì)象.

以上就是個(gè)人對(duì)block的一些理解, 很可能有理解不到位的地方, 還請(qǐng)各位看官多多指正!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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