缘由: 今天在看项目的时候,发现其中一同事,将所有控件的属性都设置为
weak
,而我自己想想我平常基本都是用strong
啊,当然 XIB 或 stroyboard 例外,所以特此多加了解下。
回顾下,我们控件一般是怎样创建的呢?
1、 从storyboard或者xib创建
@property (weak, nonatomic) IBOutlet UIScrollView *myScrollerView;
从storyboard或者xib创建为什么用 weak? 注意控件在 View 上时,它们已经形成的引用关系:
UIViewController => UIView => subView => myScrollerView
此时就相当于 XIB 对其已经强引用啦,所以你你声明的属性对它是弱引用。另外我觉的下面这句话,非常到位。因为控件他爹( view.superview )已经揪着它的小辫了( strong reference ),你( viewController )眼瞅着( weak reference )就好了。
总之,设为weak是因为它已经被view引用了,除非view被释放,否则IBOutlet的属性也不会被释放,另外IBOutlet属性的生命周期和view应该是一致的,所以IBOutlet属性一般设为weak。
2、 手动创建并声明strong或者weak
@property (nonatomic, strong) UIButton *testButton;
@property (nonatomic, weak) UILabel *testLabel;
我是一般用 strong,我们再观察下,下面两种的实际用法
// strong
self.testButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.view addSubview:self.testButton];
// weak
UILabel *label = [[UILabel alloc] init];
self.testLabel = label;
[self.view addSubview:self.testLabel];
其实不管声明的属性是强引用还是弱引用,在控制器消失的时候,这个属性消失,View消失,subViews消失,控件也就消失了。
在手动创建的时候,使用 weak并没有什么特殊的优势,相反这块不注意写法的话,还容易对象会因无引用者立即被释放,造成问题。
另外注意一原则:UIViewController下的view,由于viewcontroller直接拥有该view,那就应该选择strong。而如果控件是viewcontroller中view的子视图,对于这个子视图,它的所有者是它的父视图,代码中只是想引用一下这个子视图的指针而已,那么就应该选择weak。
所以我们手动创建这块,对于控件使用还是用 strong 吧!
补充:通过这篇 Xcode 7中Interface Builder的新特性中了解到 在 iOS 9后 在IBOutlets定义weak是可以说是没意义的。
参考
http://birdmichael.com/?p=500
https://www.zhihu.com/question/29927614