引言
相信大家對(duì)block的使用都不會(huì)感到陌生, __weak和__strong也成為了大家解決循環(huán)引用的利器. 不過大家有否想過, block出現(xiàn)嵌套情況時(shí), __weak和__strong還能好使嗎, 或者說會(huì)不會(huì)有一些需要注意的地方呢?
正篇
首先我們定義了一個(gè)Person類, .h中只有1個(gè)無參無返回的block屬性 -> personBlock, 并且重寫了dealloc方法, 如下圖所示:


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

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

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

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

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

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

補(bǔ)充
另外想補(bǔ)充一個(gè)關(guān)于block強(qiáng)引用對(duì)象的問題, 之前在網(wǎng)上看到過一些說法, 大概就是block會(huì)對(duì)內(nèi)部所有的對(duì)象產(chǎn)生一個(gè)強(qiáng)引用, 比如說:
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)引用的問題.
首先我們?cè)趧偛糯a的基礎(chǔ)上加一個(gè)Dog類, 只重寫其中的dealloc方法:

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

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

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