iOS中delegate和IBOutlet为何使用弱引用

有时候一些理所当然的事,一细想之后才发现,没那么简单。

问:为何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了。

如果有不正确的地方欢迎指出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容