相信很多人都知道,从IB中拖出来的outlet 默认是weak的 那么纯代码搭建view时 是应该怎样声明view对象呢?
首先我们先尝试将代码中的view 属性设置成weak实现一下,看一下效果怎么样
@property (nonatomic,weak) UILabel *label;
将label声明成weak后在viewDidLoad中初始化label
self.label = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
self.label.text = @"hello my world!!";
[self.view addSubview:self.label];
这时候编译器会给我们报一个警告
再尝试运行一下,果然屏幕上什么也没有。
那我们再用strong尝试一下,看一下效果如何呢?
将weak更为strong
@property (nonatomic,strong) UILabel *label;
然后警告没有了
出现了我们添加的label
那是不是我们应该用strong 而不是用label呢?我们来看看三者之间的关系
三者之间的关系 viewController --> viewController.view --> view.subview (UIView)
我们看到,其实label的所有者其实是self.view,那么在viewcontroller中声明labelweak应该是正确的,如果声明为strong 那么在label从self.view中移除时,label将不会被释放。造成view的冗余,那么为什么声明成weak的时候,label又没有出现呢?
如果声明成weak 过程是这样的:
//我们声明了label
self.label = [UILabel alloc] initWithFrame:CGRectMake(50,50,100,100);
//其实是这样一个过程
id temp = [UILabel alloc] initWithFrame:CGRectMake(50,50,100,100);//temp此时引用计数为1
[self setLabel:temp];//此时引用计数仍为1
[temp release];//此时temp已经没有强引用 计数清0
//然后我们将label添加到view中去
[self.view addSubview:self.label];//其实是添加的一个nil对象,当然屏幕上没有显示,那么应该怎样声明才是正确的呢?
我们刚刚说了strong肯定是不合适的,但是能够达到我们的想要的效果,但是一旦view增多,造成的内存泄露越来越严重,这个是我们不想要看到的。
正确的操作方式
UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
self.label = tempLabel;
self.label.text = @"hello my world!!";
[self.view addSubview:self.label];
这样在我们的屏幕上就会出现label了
这段话的执行过程是:
UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];
//执行过程
// id temp = [[UILabel alloc] initWithFrame:CGRectMake(50, 50, 100, 100)];//temp计数1
// UILabel *tempLabel = temp;//temp 计数为2
self.label = tempLabel;//label的属性为weak 引用计数不增加 依然为2
[self.view addSubview:self.label];//temp的引用计数加1 为3
//此时 tempLabel 没有了引用 release掉
[tempLabel release]; //temp引用计数为2
//temp release掉
[temp release]; //temp引用计数为1
所以这样 我们的label依然还是没有被释放掉的
这样的初始化方法 是比较科学的 如有不当之处 敬请指出 我们一起学习成长!
本篇文章有参考
http://stackoverflow.com/questions/9747015/why-is-addsubview-not-retaining-the-view