有时候一些理所当然的事,一细想之后才发现,没那么简单。
问:为何delegate要用weak引用,而不是strong?
答:避免循环引用,防止内存泄漏!
好!假设有AVC和BVC两个ViewController,AVC推出BVC,在推出BVC之前,AVC将自己设为BVC的delegate。代码看起来是这样的:
// AVC.m
- (void)pushBVC
{
BVC *bvc = [BVC new];
bvc.delegate = self;
[self.navigationController pushViewController: bvc animated:YES];
}
在这样的环境下,如果bvc的delegate引用如果是strong,是否会造成循环引用?
// BVC.h
@property (nonatomic, strong) id<BVCDelegate> delegate;
来分析一下。bvc的delegate指向了AVC的实例,是个强引用。但是,AVC实例并没有引用bvc这块对象,只是将bvc压到navigationController的栈里了。所以并没有循环引用。
那为什么我们平时都用weak而不用strong呢?
一、就这种情况下而言,如果使用了strong,avc的引用计数+1。然而在栈里面,bvc一定是比avc先释放的,bvc一释放,引用计数又减1了。也就是说这个引用计数+1的操作一点意义都没有。bvc在,avc一定在。
二、再说说UITableView的delegate和datasource,这里如果改成strong引用,对不起,循环引用!为什么,因为这个tableview确确实实是当前vc所持有的,是strong引用了的,而这时如果tableview再strong引用自己的delegate or datasource,肯定循环引用。所以这种情况下,必须用weak。
三、那IBOutlet呢,一般都是weak,能用strong么?
viewfromxib.png看图说话,我们创建VC的同时创建的xib,等同于我们操作的self.view, self对view是强引用的,所有这些子view又都在self.view.subviews的数组中,也就是已经强引用这些子view了,所以我们在IBOutlet的时候无需再用strong,weak就行。看下图:
subviewlist.png
如果你用了strong,引用计数一定还会再+1,这时子视图可能就会释放不掉,你需要自己在正确的时机释放。
还有一种情况,你的xib中除了原先的view之外,又创建了一个viewB,这个时候viewB没有被任何人引用,和self.view也没有关系,也不在self.view.subviews中。那么你在IBOutlet链接这个viewB的时候就必须用strong,而不是weak了。
如果有不正确的地方欢迎指出。
网友评论