有時(shí)候一些理所當(dāng)然的事,一細(xì)想之后才發(fā)現(xiàn)窿祥,沒那么簡(jiǎn)單。
問:為何delegate要用weak引用蝙寨,而不是strong?
答:避免循環(huán)引用晒衩,防止內(nèi)存泄漏!
好墙歪!假設(shè)有AVC和BVC兩個(gè)ViewController听系,AVC推出BVC,在推出BVC之前虹菲,AVC將自己設(shè)為BVC的delegate靠胜。代碼看起來是這樣的:
// AVC.m
- (void)pushBVC
{
BVC *bvc = [BVC new];
bvc.delegate = self;
[self.navigationController pushViewController: bvc animated:YES];
}
在這樣的環(huán)境下,如果bvc的delegate引用如果是strong毕源,是否會(huì)造成循環(huán)引用髓帽?
// BVC.h
@property (nonatomic, strong) id<BVCDelegate> delegate;
來分析一下。bvc的delegate指向了AVC的實(shí)例脑豹,是個(gè)強(qiáng)引用郑藏。但是,AVC實(shí)例并沒有引用bvc這塊對(duì)象瘩欺,只是將bvc壓到navigationController的棧里了必盖。所以并沒有循環(huán)引用拌牲。
那為什么我們平時(shí)都用weak而不用strong呢?
一歌粥、就這種情況下而言塌忽,如果使用了strong,avc的引用計(jì)數(shù)+1失驶。然而在棧里面土居,bvc一定是比avc先釋放的,bvc一釋放嬉探,引用計(jì)數(shù)又減1了擦耀。也就是說這個(gè)引用計(jì)數(shù)+1的操作一點(diǎn)意義都沒有。bvc在涩堤,avc一定在眷蜓。
二、再說說UITableView的delegate和datasource胎围,這里如果改成strong引用吁系,對(duì)不起,循環(huán)引用白魂!為什么汽纤,因?yàn)檫@個(gè)tableview確確實(shí)實(shí)是當(dāng)前vc所持有的,是strong引用了的福荸,而這時(shí)如果tableview再strong引用自己的delegate or datasource蕴坪,肯定循環(huán)引用。所以這種情況下逞姿,必須用weak。
三捆等、那IBOutlet呢滞造,一般都是weak,能用strong么栋烤?
看圖說話谒养,我們創(chuàng)建VC的同時(shí)創(chuàng)建的xib,等同于我們操作的self.view, self對(duì)view是強(qiáng)引用的明郭,所有這些子view又都在self.view.subviews的數(shù)組中买窟,也就是已經(jīng)強(qiáng)引用這些子view了,所以我們?cè)贗BOutlet的時(shí)候無需再用strong薯定,weak就行始绍。看下圖:
如果你用了strong话侄,引用計(jì)數(shù)一定還會(huì)再+1亏推,這時(shí)子視圖可能就會(huì)釋放不掉学赛,你需要自己在正確的時(shí)機(jī)釋放。
還有一種情況吞杭,你的xib中除了原先的view之外盏浇,又創(chuàng)建了一個(gè)viewB,這個(gè)時(shí)候viewB沒有被任何人引用芽狗,和self.view也沒有關(guān)系绢掰,也不在self.view.subviews中。那么你在IBOutlet鏈接這個(gè)viewB的時(shí)候就必須用strong童擎,而不是weak了滴劲。
如果有不正確的地方歡迎指出。