__weak和__strong的使用

1. 使用場(chǎng)景

??一般我們?cè)谑褂胋lock的時(shí)候, 都會(huì)特意去注意一個(gè)問(wèn)題--循環(huán)引用的問(wèn)題, 根據(jù)OC的引用計(jì)數(shù)機(jī)制, 當(dāng)對(duì)象的引用計(jì)數(shù)為0的時(shí)候, 系統(tǒng)會(huì)釋放這個(gè)對(duì)象. 循環(huán)引用會(huì)導(dǎo)致我們的對(duì)象不能正常釋放, 類(lèi)似資源爭(zhēng)奪的現(xiàn)象, 釋放A的條件是B的釋放, 而釋放B的條件是釋放A.

1.1 聲明一個(gè)是TestViewController里面定義一個(gè)block--callBack

@interface TestViewController : UIViewController
@property (nonatomic, copy) void(^callBack)(NSString* name);
@end

1.2在viewDidLoad里面實(shí)現(xiàn)并調(diào)用block

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setCallBack:^(NSString *name) {
        NSLog(@"%@ %@", self, name);
    }];
    self.callBack(@"come on");
}
- (void)dealloc
{
    NSLog(@"%@ dealloc ", self);
}

這個(gè)代碼里面是一個(gè)最基礎(chǔ)的循環(huán)引用問(wèn)題(測(cè)試貼圖), 一般我們解決此類(lèi)問(wèn)題需要有一個(gè)弱引用也就是我們所要講述的__weak,代碼如下

- (void)viewDidLoad {
    [super viewDidLoad];
    __weak typeof(self) weakSelf = self;
    [self setCallBack:^(NSString *name) {
        NSLog(@"%@ %@", weakSelf, name);
    }];
    self.callBack(@"come on");
}

這樣的話, TestViewController就可以正常的dealloc了.

2. 注意事項(xiàng)

這樣寫(xiě)會(huì)存在一定的隱患, 因?yàn)開(kāi)_weak類(lèi)型在這里是個(gè)局部變量, 而且weak屬性有個(gè)特點(diǎn)就是自動(dòng)置為nil, 所以有可能在我們?nèi)ナ褂脀eakSelf的時(shí)候, weakSelf已經(jīng)是空值了.

- (void)viewDidLoad {
    [super viewDidLoad];
    __weak typeof(self) weakSelf = self;
    [self setCallBack:^(NSString *name) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [NSThread sleepForTimeInterval:5];
            NSLog(@"%@ %@", weakSelf, name);
        });
    }];
    self.callBack(@"come on");
}

輸出結(jié)果是

2017-12-23 11:50:00.450854+0800 循環(huán)引用問(wèn)題[5620:207264] <TestViewController: 0x7fc43ae025b0> dealloc
2017-12-23 11:50:02.952027+0800 循環(huán)引用問(wèn)題[5620:207367] (null) come on

會(huì)先delloc, 然后才會(huì)走block里面的代碼. 可以看到此時(shí)的weakSelf已經(jīng)是null了, 如果我們做如下修改

- (void)viewDidLoad {
    [super viewDidLoad];
    __weak typeof(self) weakSelf = self;
    [self setCallBack:^(NSString *name) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [NSThread sleepForTimeInterval:5];
            NSLog(@"%@ %@", strongSelf, name);
        });
    }];
    self.callBack(@"come on");
}

輸出結(jié)果如下

2017-12-23 11:57:05.182026+0800 循環(huán)引用問(wèn)題[5709:215351] <TestViewController: 0x7ff217725e50> come on
2017-12-23 11:57:05.182414+0800 循環(huán)引用問(wèn)題[5709:214769] <TestViewController: 0x7ff217725e50> dealloc

__strong可以使block對(duì)self進(jìn)行強(qiáng)制持有, 使他的retainCount+1, 使self不能dealloc, 而strongSelf是個(gè)局部變量, 當(dāng)block結(jié)束的時(shí)候就會(huì)自動(dòng)釋放掉, 所以此時(shí)的self的self的retainCount-1, 然后可以釋放掉self.

- (void)viewDidLoad {
    [super viewDidLoad];
    __weak typeof(self) weakSelf = self;
    [self setCallBack:^(NSString *name) {
        NSLog(@"strong之前:%lu", CFGetRetainCount((__bridge CFTypeRef)(((NSObject *)weakSelf))));
        __strong typeof(weakSelf) strongSelf = weakSelf;
        NSLog(@"strong之后:%lu", CFGetRetainCount((__bridge CFTypeRef)(((NSObject *)weakSelf))));
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [NSThread sleepForTimeInterval:5];
            NSLog(@"%@ %@", strongSelf, name);
        });
    }];
    self.callBack(@"come on");
}

輸出結(jié)果是

2017-12-23 12:01:57.725400+0800 循環(huán)引用問(wèn)題[5782:221024] strong之前:10
2017-12-23 12:01:57.725636+0800 循環(huán)引用問(wèn)題[5782:221024] strong之后:11
2017-12-23 12:02:02.729803+0800 循環(huán)引用問(wèn)題[5782:221561] <TestViewController: 0x7f8bc6f04230> come on
2017-12-23 12:02:02.730176+0800 循環(huán)引用問(wèn)題[5782:221024] <TestViewController: 0x7f8bc6f04230> dealloc

可以看到strong之后的retainCount+1了.

源碼地址
https://github.com/autmaple/RetainCycleProblem

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子套鹅,更是在濱河造成了極大的恐慌,老刑警劉巖揽祥,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異檩电,居然都是意外死亡拄丰,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)俐末,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)料按,“玉大人,你說(shuō)我怎么就攤上這事卓箫≡乜螅” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵烹卒,是天一觀的道長(zhǎng)闷盔。 經(jīng)常有香客問(wèn)我,道長(zhǎng)旅急,這世上最難降的妖魔是什么逢勾? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮藐吮,結(jié)果婚禮上溺拱,老公的妹妹穿的比我還像新娘。我一直安慰自己谣辞,他們只是感情好迫摔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著泥从,像睡著了一般句占。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上歉闰,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天辖众,我揣著相機(jī)與錄音,去河邊找鬼和敬。 笑死凹炸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昼弟。 我是一名探鬼主播啤它,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼舱痘!你這毒婦竟也來(lái)了变骡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤芭逝,失蹤者是張志新(化名)和其女友劉穎塌碌,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體旬盯,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡台妆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胖翰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片接剩。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖萨咳,靈堂內(nèi)的尸體忽然破棺而出懊缺,到底是詐尸還是另有隱情,我是刑警寧澤培他,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布鹃两,位于F島的核電站,受9級(jí)特大地震影響靶壮,放射性物質(zhì)發(fā)生泄漏怔毛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一腾降、第九天 我趴在偏房一處隱蔽的房頂上張望拣度。 院中可真熱鬧,春花似錦螃壤、人聲如沸抗果。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)冤馏。三九已至,卻和暖如春寄啼,著一層夾襖步出監(jiān)牢的瞬間逮光,已是汗流浹背代箭。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涕刚,地道東北人嗡综。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像杜漠,于是被迫代替她去往敵國(guó)和親极景。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

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