引言
相信大家對(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方法, 如下圖所示:


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

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

為了解決循環(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:

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

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

只要在最后把外層的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)被使用:

補(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方法:

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

正篇開(kāi)始, 我們?cè)谥鞣椒ㄖ蟹謩e創(chuàng)建person和dog對(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í)刻:

結(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ì)象.