關于 Block 導致的循環(huán)引用

,經(jīng)常說在 block 里面很容易導致循環(huán)引用(retain cycle),可是為什么會導致循環(huán)引用,卻不是特別理解,最近研究了,也算是做一個總結.

常見的循環(huán)引用

看看這個類
代碼1

@interface TestClass : NSObject
@property (nonatomic,copy)void (^block)();
-(void)test;
@end

有一個屬性, block,一個方法 test
來看看類實現(xiàn)
代碼2

@implementation TestClass
-(void)dealloc{
    NSLog(@"dealloc");
}
-(void)test{
    self.block=^{
        NSLog(@"%@",self);
    };
}
@end

可以看到, test方法中有一個明顯的在 self.block中調(diào)用self的過程.來看看會不會導致循環(huán)引用.
接下來,隨便在其他類中來調(diào)用一下這個類
代碼3

TestClass* test=[TestClass new];
[test test];

運行試試

2016-01-29 10:55:14.035 test[16318:1121947] <TestClass: 0x7fd3eb52b250>**

沒有輸出 "dealloc",說明 test對象沒有被釋放,怎么辦?
很簡單就會想到使用弱引用,
來看看使用弱引用的代碼
代碼4

-(void)test{
    __weak typeof(self) weakself=self;
    self.block=^{
        NSLog(@"%@",weakself);
    };
    self.block();
}

輸出

2016-01-29 10:58:01.899 test[16360:1124161] <TestClass: 0x7f9d61c4c240>
2016-01-29 10:58:01.899 test[16360:1124161] dealloc

可以看到, self 被成功釋放了,沒有被循環(huán)引用.

為什么?

首先, block 會自動捕獲block 內(nèi)部使用的變量,并對其強引用.具體過程可以參考 Objective-C高級編程.
在本例中代碼2, block 內(nèi)部有 self ,因為self 本身是一個強引用,所以block 會再給 self 加上一個強引用.
block 本身是self 的一個屬性,self也強持有block.
這就出現(xiàn)一個問題, self強持有block,block 強持有self,當self想要釋放的時候,要看一下有沒有自己強引用,而 block剛好強持有自己,所以,暫時沒辦法釋放.block 想要釋放的時候,卻發(fā)現(xiàn) self強持有自己,所以也得不到釋放,相互糾纏.

而為何代碼4 又可以呢?
代碼4中, block 內(nèi)部有一個 weakself,weakself 本身是一個弱引用,由于對弱引用無法強持有,所以, block 并沒有強持有self,當 self 想要釋放的時候,已經(jīng)沒有其他強引用了,就可以釋放.self被釋放,就沒有變量強持有block,block也會釋放.這樣,循環(huán)引用就不存在了.

引申

既然只要不相互持有就可以,那么我們手動的去掉強引用還會不會發(fā)生循環(huán)引用呢?
看看這個代碼.
代碼5

-(void)test{
    self.block=^{
        NSLog(@"%@",self);
    };
    self.block();
    self.block=nil;
}

這里在執(zhí)行完畢后,手動去掉了 block 的強引用.由于打破了相互引用,自然也不會有循環(huán)引用.
看看輸出

2016-01-29 11:25:25.238 test[16439:1133368] <TestClass: 0x7fb381511b80>
2016-01-29 11:25:25.239 test[16439:1133368] dealloc

果然如此,不過這種方法畢竟很不安全,要是block是需要在一段時間后調(diào)用的,如果你馬上就釋放了,那么 block 中代碼就不能執(zhí)行.又或者,如果你忘記手動釋放,也會造成很大麻煩,相對之下,使用 weakself就好多了.
另外,在使用weakself的時候,可以和strongself一起使用,可以參考我的文章為什么要用 strongSelf

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

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

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