xib 或 storyboard 中拖过来的控件
当我们从 xib 或者 storyboard 上拖控件到代码中的时候,我们会发现默认是用 weak 属性修饰的,当然还有一个 IBOutlet 前缀。例如:
@property(weak,nonatomic)IBOutletUIButton*btn;
为什么这里要用 weak 修饰?
首先来看看 IBOutlet 有什么作用。IBOutlet 其实就是一个声明,它不做任何事情,仅仅表明该变量与界面的某个元素相连。
而这里使用 weak,则是因为在 xib 或者 storyboard 文件中已经对该控件形成了一个强引用。在将控件拖到 xib 或者 storyboard 上时,view 对它形成了一个强引用,那么在 viewcontroller 的代码文件中,它只需要弱引用这个控件就行了。
当 view 被释放,那么这个属性自然也就会被释放,控件生命周期与其拥有者保持一致。
事实上,当把 viewcontroller 拥有的 view 拖到代码文件中的时候,使用的是 strong 修饰。因为这个 view 正是被 viewcontroller 所拥有。
代码创建 UI 控件
那么,当我们不使用 xib 或者 storyboard 创建 UI 控件的时候,应该使用什么修饰符呢?
我们可以尝试一下 weak:
使用weak修饰 _userImageView
会产生如上警告,警告中说:object will be released after assignment. 对象将在分配后被释放。这是因为没有其他的强引用存在了,weak 指针自然会被释放。当然在此处,由于下面又使用了 addSubview 方法,对其加了一个强引用,所以也没有什么问题。但是在此处,还是推荐使用 strong 修饰符。
在ARC中,对象释放的最终根据还是根据引用计数为0时去释放。而weak与strong的根本区别是在set方法中,weak的set方法和strong的set方法都是释放旧值保留新值,但是weak的set方法会对其autorelease,即延迟release一次,而strong的set方法也是释放旧值保留新值,但是其不会延迟release。最终效果是strong会+1,weak不会+1.
要注意,用_去赋值的时候是不调用set方法的,也就是说无论weak还是strong,只要用_赋值都不会对引用计数加1,区别在于self.语法会调用set方法,strong的self.会调用set方法+1.而weak的_和self.语法都不会+1.
那么我们在开发中,到底是用weak还是用strong?
1、如果你真的怕麻烦,也不想理解什么内存管理,你就用strong就对了。
2、可以分情况来看,如果你用strong修饰了属性,并且也addSubview:了,虽然引用计数为2,但是当整个父视图被销毁的时候,这两个引用计数都会变成0,所以不会造成内存泄漏。
3、具体的情况就是,我们有时候在一个视图1中,需求要求我们声明一个视图2,这个视图2不一定是视图1的子视图,此时假如视图2有值:那么weak时,引用计数为0,这个视图相当于不存在。strong时,引用计数为1,不管你添加不添加到视图1的子视图,视图2都存在。简要概括: