ios-關(guān)于block的循環(huán)應(yīng)用問題

個人補充:?? xcode斷點后,點擊下面按鈕,可以看到指針引用導(dǎo)圖,很快能看出有沒有循環(huán)引用



一.

Objective C 的 Block 是一個很實用的語法,特別是與GCD結(jié)合使用,可以很方便地實現(xiàn)并發(fā)、異步任務(wù)。但是,如果使用不當(dāng),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 官方的建議是,傳進(jìn) Block 之前,把 ‘self’ 轉(zhuǎn)換成 weak automatic 的變量,這樣在 Block 中就不會出現(xiàn)對 self 的強引用。如果在 Block 執(zhí)行完成之前,self 被釋放了,weakSelf 也會變?yōu)?nil。

示例代碼:

1 __weak __typeof__(self) weakSelf = self;

2? ? dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

3? ? [weakSelf doSomething];

4 });

clang 的文檔表示,在 doSomething 內(nèi),weakSelf 不會被釋放。但,下面的情況除外:

1 __weak __typeof__(self) weakSelf = self;

2? ? dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

3? ? [weakSelf doSomething];

4? ? [weakSelf doOtherThing];

5 });

在 doSomething 中,weakSelf 不會變成 nil,不過在 doSomething 執(zhí)行完成,調(diào)用第二個方法 doOtherThing 的時候,weakSelf 有可能被釋放,于是,strongSelf 就派上用場了:

1 __weak __typeof__(self) weakSelf = self;

2? ? dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

3? ? __strong __typeof(self) strongSelf = weakSelf;

4? ? [strongSelf doSomething];

5? ? [strongSelf doOtherThing];

6 });

__strong 確保在 Block 內(nèi),strongSelf 不會被釋放。

總結(jié)

在 Block 內(nèi)如果需要訪問 self 的方法、變量,建議使用 weakSelf。

如果在 Block 內(nèi)需要多次 訪問 self,則需要使用 strongSelf。

原文作者: lslin

原文鏈接: http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block/

版權(quán)聲明:自由轉(zhuǎn)載-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0


二.

block是控制器的屬性,如果block內(nèi)部沒有使用weakSelf將會造成內(nèi)存泄露

self.testBlock = ^()

{

NSLog(@"%@",self.mapView);

};

self.testBlock();

把block內(nèi)部抽出一個作為self的方法,當(dāng)使用weakSelf調(diào)用這個方法,并且這個方法里有self的屬性,block不會造成內(nèi)存泄露

self.testBlock = ^()

{

[weakSelf test];

};

-(void)test

{

NSLog(@"%@",self.mapView);

}

當(dāng)block不是self的屬性時,block內(nèi)部使用self也不會造成內(nèi)存泄露

TestBlock testBlock = ^()

{

NSLog(@"%@",self.mapView);

};

[self test:testBlock];

當(dāng)使用類方法有block作為參數(shù)使用時,block內(nèi)部使用self也不會造成內(nèi)存泄露

[WDNetwork testBlock:^(id responsObject) {

NSLog(@"%@",self.mapView);

}];

文/iOSWoden

原文鏈接:http://www.itdecent.cn/p/c6ca540861d9

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

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

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