ios內(nèi)存管理 — __weak和__strong使用

最近在查閱一些第三方庫(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修飾符的問題

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市站绪,隨后出現(xiàn)的幾起案子遭铺,更是在濱河造成了極大的恐慌,老刑警劉巖恢准,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魂挂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡馁筐,警方通過查閱死者的電腦和手機(jī)涂召,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)敏沉,“玉大人果正,你說(shuō)我怎么就攤上這事炎码。” “怎么了秋泳?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵潦闲,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我迫皱,道長(zhǎng)歉闰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任舍杜,我火速辦了婚禮,結(jié)果婚禮上赵辕,老公的妹妹穿的比我還像新娘既绩。我一直安慰自己,他們只是感情好还惠,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布饲握。 她就那樣靜靜地躺著,像睡著了一般蚕键。 火紅的嫁衣襯著肌膚如雪救欧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天锣光,我揣著相機(jī)與錄音笆怠,去河邊找鬼。 笑死誊爹,一個(gè)胖子當(dāng)著我的面吹牛蹬刷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播频丘,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼办成,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了搂漠?” 一聲冷哼從身側(cè)響起迂卢,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎桐汤,沒想到半個(gè)月后而克,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怔毛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年拍摇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片馆截。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡充活,死狀恐怖蜂莉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情混卵,我是刑警寧澤映穗,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站幕随,受9級(jí)特大地震影響蚁滋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜赘淮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一辕录、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧梢卸,春花似錦走诞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至戴陡,卻和暖如春塞绿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背恤批。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工异吻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喜庞。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓涧黄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親赋荆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子笋妥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容