昨天和同事在看代碼的時(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