Objective C 的Block是一個很實用的語法,特別是與GCD結(jié)合使用堤瘤,可以很方便地實現(xiàn)并發(fā)玫芦、異步任務(wù)。但是本辐,如果使用不當桥帆,Block 也會引起一些循環(huán)引用問題(retain cycle)—— Block 會 retain ‘self’,而 ‘self‘ 又 retain 了 Block慎皱。因為在 ObjC 中老虫,直接調(diào)用一個實例變量,會被編譯器處理成 ‘self->theVar’茫多,’self’ 是一個 strong 類型的變量祈匙,引用計數(shù)會加 1,于是天揖,self retains queue夺欲, queue retains block祭芦,block retains self秘车。
解決 retain circle
Apple 官方的建議是,傳進 Block 之前,把 ‘self’ 轉(zhuǎn)換成 weak automatic 的變量万细,這樣在 Block 中就不會出現(xiàn)對 self 的強引用。如果在 Block 執(zhí)行完成之前纸泄,self 被釋放了赖钞,weakSelf 也會變?yōu)?nil。
示例代碼:
__weak__typeof__(self)weakSelf=self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
[weakSelfdoSomething];
});
clang 的文檔表示聘裁,在 doSomething 內(nèi)雪营,weakSelf 不會被釋放。但衡便,下面的情況除外:
__weak__typeof__(self)weakSelf=self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
[weakSelfdoSomething];
[weakSelfdoOtherThing];
});
在 doSomething 中献起,weakSelf 不會變成 nil洋访,不過在 doSomething 執(zhí)行完成,調(diào)用第二個方法 doOtherThing 的時候谴餐,weakSelf 有可能被釋放姻政,于是,strongSelf 就派上用場了:
__weak__typeof__(self)weakSelf=self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
__strong__typeof(self)strongSelf=weakSelf;
[strongSelfdoSomething];
[strongSelf doOtherThing];
});
__strong確保在 Block 內(nèi)岂嗓,strongSelf 不會被釋放汁展。
總結(jié)
在 Block 內(nèi)如果需要訪問 self 的方法、變量厌殉,建議使用 weakSelf食绿。
如果在 Block 內(nèi)需要多次 訪問 self,則需要使用 strongSelf公罕。