最近在查閱一些第三方庫(kù)的源碼時(shí)迅诬,發(fā)現(xiàn)了這么一段代碼
__weak typeof(self) weakself = self;
delay(time, ^{
__strong typeof(weakself) strongSelf = weakself;
if (strongSelf) {
[strongSelf hide];
}
});
還有在AFNetWorking中
__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
在ARC環(huán)境下形导,我們經(jīng)常會(huì)使用__weak 的修飾符來(lái)修飾一個(gè)變量扫茅,防止其在block中被循環(huán)引用的情況發(fā)生琐凭,但是有些特殊情況下暂衡,我們?cè)赽lock中又使用__strong 來(lái)修飾這個(gè)在block外剛剛用__weak修飾的變量询微。
經(jīng)過查詢,還是找到了這么一篇文章
轉(zhuǎn)自唐巧的關(guān)于__weak和__strong詳解
文中大概是這么解釋的
在block中調(diào)用self會(huì)引起循環(huán)引用狂巢,但是在block中需要對(duì)weakSelf進(jìn)行strong,保證代碼在執(zhí)行到block中拓提,self不會(huì)被釋放,當(dāng)block執(zhí)行完后隧膘,會(huì)自動(dòng)釋放該strongSelf代态。
在 block 中先寫一個(gè) strong self,其實(shí)是為了避免在 block 的執(zhí)行過程中疹吃,突然出現(xiàn) self 被釋放的尷尬情況蹦疑。通常情況下,如果不這么做的話萨驶,還是很容易出現(xiàn)一些奇怪的邏輯歉摧。
1.概念
__strong的概念
__strong修飾符是id類型和對(duì)象類型默認(rèn)的所有權(quán)修飾符。
__strong修飾符表示對(duì)對(duì)象的強(qiáng)引用,持有強(qiáng)引用的變量在出其作用域時(shí)被廢棄叁温,隨著強(qiáng)引用的失效再悼,引用的對(duì)象隨之釋放。
__weak的概念
__weak 解決循環(huán)引用膝但,帶有__weak修飾符的變量不持有對(duì)象冲九,所以在超出其變量作用域時(shí),對(duì)象即被釋放跟束。
在解釋上述代碼時(shí)莺奸,還是先通過代碼來(lái)理解下這兩種修飾符的不同。
1.創(chuàng)建一個(gè)person類
2.實(shí)例化person,并給與修飾符__weak
person * p1 = [[person alloc]init];
__weak person * p2 = p1;
p1 = nil;
NSLog(@"__weak修飾 p1=%@ p2=%@",p1,p2);
打印結(jié)果
__weak修飾 p1=(null)p2=(null)
我們通過代碼可以得出
當(dāng)p1設(shè)為nil后冀宴,__weak修飾的p2也為nil.
我們來(lái)使用修飾符__strong
person * p1 = [[person alloc]init];
__strong person* p2 = p1;
p1 = nil;
NSLog(@"__strong修飾 p1=%@ p2=%@",p1,p2);
打印結(jié)果
__strong修飾 p1=(null) p2=<person: 0x604000013060>
可以看到
當(dāng)p1設(shè)為nil后灭贷,__strong修飾的p2仍然存在。
我們還是重現(xiàn)下文中前兩段代碼的使用方法
1.在person類中略贮,dealloc方法中
-(void)dealloc
{
NSLog(@"dealloc -- 方法調(diào)用%@",[self class]);
}
2.使用__weak修飾甚疟,每隔1s打印一次,3s后將p1置為nil
#import "ViewController.h"
#import "person.h"
@interface ViewController ()
@property (nonatomic,strong) person * p1;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
person* p1 = [[person alloc]init];
self.p1= p1;
__weak person* weakp2 = self.p1;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSInteger count =0;
// __strong person* strongP2 = weakp2;
while(count<5) {
count++;
// 阻塞一秒執(zhí)行一次
NSLog(@"__weak 修飾 %@",weakp2);
// NSLog(@"__strong修飾 %@",strongP2);
sleep(1);
}
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2*NSEC_PER_SEC)),dispatch_get_main_queue(), ^{
self.p1= nil;
});
}
打印結(jié)果如下
2018-03-25 12:56:57.338597+0800 testCode[72562:3533996] __weak 修飾 <person: 0x60000000bdf0>
2018-03-25 12:56:58.342259+0800 testCode[72562:3533996] __weak 修飾 <person: 0x60000000bdf0>
2018-03-25 12:56:59.338610+0800 testCode[72562:3533876] dealloc -- 方法調(diào)用person
2018-03-25 12:56:59.347271+0800 testCode[72562:3533996] __weak 修飾 (null)
2018-03-25 12:57:00.348689+0800 testCode[72562:3533996] __weak 修飾 (null)
2018-03-25 12:57:01.352773+0800 testCode[72562:3533996] __weak 修飾 (null)
我們可以得到逃延,只使用__weak去修飾變量古拴,當(dāng)別處把變量釋放后,block中該變量也會(huì)被釋放掉真友。
接下來(lái)我們?cè)赺_block的方法內(nèi)部加上__strong修飾符
- (void)viewDidLoad {
[super viewDidLoad];
person* p1 = [[person alloc]init];
self.p1= p1;
__weak person* weakp2 = self.p1;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSInteger count =0;
__strong person* strongP2 = weakp2;
while(count<5) {
count++;
// 阻塞一秒執(zhí)行一次
NSLog(@"__strong修飾 %@",strongP2);
sleep(1);
}
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2*NSEC_PER_SEC)),dispatch_get_main_queue(), ^{
self.p1= nil;
});
}
打印結(jié)果如下
2018-03-25 13:02:21.385418+0800 testCode[72600:3537337] __strong修飾 <person: 0x6040000106a0>
2018-03-25 13:02:22.388769+0800 testCode[72600:3537337] __strong修飾 <person: 0x6040000106a0>
2018-03-25 13:02:23.391824+0800 testCode[72600:3537337] __strong修飾 <person: 0x6040000106a0>
2018-03-25 13:02:24.395673+0800 testCode[72600:3537337] __strong修飾 <person: 0x6040000106a0>
2018-03-25 13:02:25.399132+0800 testCode[72600:3537337] __strong修飾 <person: 0x6040000106a0>
2018-03-25 13:02:26.402472+0800 testCode[72600:3537337] dealloc -- 方法調(diào)用person
在__block中修飾后的方法中黄痪,再加上修飾符strong時(shí),當(dāng)別處把變量釋放掉盔然,但調(diào)用該變量的block如果仍然沒有執(zhí)行結(jié)束桅打,那么系統(tǒng)就會(huì)等待block執(zhí)行完成后再釋放,對(duì)該變量在block中的使用起到了保護(hù)作用愈案。當(dāng)block執(zhí)行結(jié)束后會(huì)自動(dòng)釋放掉挺尾。
本文代碼及結(jié)論參考 骨頭 的一篇文章
block 中使用__weak 和__strong修飾符的問題