昨天和同事在看代碼的時(shí)候,讀到一段用
__block的地方,然而就想此處為什么要用__block呢,一分析通俗的說(shuō)就是是為了讓在當(dāng)前的Block里面可以滿足被改動(dòng)的情況,事后想想,__weak和__strong在Block中也是常用的,在此統(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