__block & __weak & __strong

昨天和同事在看代碼的時(shí)候,讀到一段用 __block的地方,然而就想此處為什么要用__block呢,一分析通俗的說(shuō)就是是為了讓在當(dāng)前的 Block 里面可以滿足被改動(dòng)的情況,事后想想,__weak__strongBlock中也是常用的,在此統(tǒng)一拿來(lái)比較筆記下。

先看下AFNetworking 中摘錄的兩個(gè)代碼片段

 __block NSMutableString *query = [NSMutableString stringWithString:@""];
 [parameters enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        [query appendFormat:@"%@**%@",key,obj];
  }];
__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
      __strong __typeof(weakSelf)strongSelf = weakSelf;

      strongSelf.networkReachabilityStatus = status;
     if (strongSelf.networkReachabilityStatusBlock) {
            strongSelf.networkReachabilityStatusBlock(status);
      }
 };

從s我們大致可以看出三者的用法,以下我們?cè)?ARC中, 從使用Block 中的情況來(lái)對(duì)比一下。

1、__block

在一個(gè) block里頭如果使用了在 block之外的變數(shù),會(huì)將這份變數(shù)先復(fù)制一份再使用,也就是,在沒(méi)有特別宣告下,對(duì)于目前的block 來(lái)說(shuō),所有的外部的變數(shù)都是只可讀的,不可改的。

如果我們想讓某個(gè) block 可以改動(dòng)某個(gè)外部的變數(shù),我們則需要將這個(gè)可以被 block 改動(dòng)的變數(shù)前面加上__block。

__block int i = 1;
void (^block)(void) = ^{
     i = i + 1;
};

從另一個(gè)角度說(shuō),使用了__block關(guān)鍵字的變量會(huì)將變量從棧上復(fù)制到堆上。棧上那個(gè)變量會(huì)指向復(fù)制到堆上的變量。

2、__weak

有時(shí)在使用block 的時(shí)候,由于self 是被強(qiáng)引用的,在 ARC 下,當(dāng)編譯器自動(dòng)將代碼中的block從棧拷貝到堆時(shí),block 會(huì)強(qiáng)引用和持有self,而 self 恰好也強(qiáng)引用和持有了 block,就造成了傳說(shuō)中的循環(huán)引用。
此時(shí) __weak 就出場(chǎng)了,在變量聲明時(shí)用 __weak修飾符修飾變量 self,讓 block 不強(qiáng)引用 self,從而破除循環(huán)。

__weak __typeof(self) weakSelf = self; 
self.testBlock = ^{
       [weakSelf test];
});

ps: 弱引用不會(huì)影響對(duì)象的釋放,但是當(dāng)對(duì)象被釋放時(shí),所有指向它的弱引用都會(huì)自定被置為 nil,這樣可以防止野指針。

3、 __strong

在上述使用 block中,雖說(shuō)使用__weak,但是此處會(huì)有一個(gè)隱患,你不知道 self 什么時(shí)候會(huì)被釋放,為了保證在block內(nèi)不會(huì)被釋放,我們添加__strong

__weak __typeof(self) weakSelf = self; 
self.testBlock =  ^{
       __strong __typeof(weakSelf) strongSelf = weakSelf;
       [strongSelf test]; 
});

PS: __strong 表示強(qiáng)引用,對(duì)應(yīng)定義 property 時(shí)用到的 strong。當(dāng)對(duì)象沒(méi)有任何一個(gè)強(qiáng)引用指向它時(shí),它才會(huì)被釋放。

weakSelf是為了block不持有self,避免循環(huán)引用,而再聲明一個(gè)strongSelf是因?yàn)橐坏┻M(jìn)入block執(zhí)行,就不允許self在這個(gè)執(zhí)行過(guò)程中釋放。block執(zhí)行完后這個(gè)strongSelf會(huì)自動(dòng)釋放,沒(méi)有循環(huán)引用問(wèn)題。

比較

__block & __weak

1. __block不管是ARC還是MRC模式下都可以使用,可以修飾對(duì)象,還可以修飾基本數(shù)據(jù)類型。
2. __weak只能在ARC模式下使用,也只能修飾對(duì)象(NSString),不能修飾基本數(shù)據(jù)類型(int)。
3. __block對(duì)象可以在block中被重新賦值,__weak不可以。
4. __block對(duì)象在ARC下可能會(huì)導(dǎo)致循環(huán)引用,非ARC下會(huì)避免循環(huán)引用,__weak只在ARC下使用,可以避免循環(huán)引用。

strong & __strong

1、strong,weak 用來(lái)修飾屬性。
strong 用來(lái)修飾強(qiáng)引用的屬性;weak 用來(lái)修飾弱引用的屬性;
2、__weak, __strong 用來(lái)修飾變量.
__strong 是默認(rèn)的引用;__weak 聲明了一個(gè)可以自動(dòng) nil 化的弱引用。

參考
http://blog.lessfun.com/blog/2014/11/22/when-should-use-weakself-and-strongself-in-objc-block/
http://blog.csdn.net/abc649395594/article/details/45476925

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

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

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