对手动创建控件时weak&strong的探究

  • 本文乃己之拙见,欢迎指正,转载请注明出处。

例子1:

  • 新建了一个继承自UIView的子类ZZYView,新增了一个属性zzyText,重写了它的dealloc方法,我想看看ZZYView什么时候释放?
@property (nonatomic,copy)NSString *zzyText;  // 属性

@implementation ZZYView

// 重写Dealloc并打印数据
-(void)dealloc
{
    NSLog(@"%@----%s",self.zzyText,__func__);
}

@end
  • 在控制器ViewController中,我写了如下代码
#import "ViewController.h"
#import "ZZYView.h"

@interface ViewController ()

@property (nonatomic,weak)ZZYView *weakZView;  //弱引用

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _weakZView = [[ZZYView alloc] initWithFrame:self.view.frame];
    NSLog(@"ZZZZZ");
    _weakZView.zzyText = @"例子1_weakZView";
    _weakZView.backgroundColor = [UIColor redColor];
    [self.view addSubview:_weakZView];
}
  • 运行后打印如下,并有警告“Assigning retained object to weak variable; object will be released after assignment”
2017-02-15 13:47:34.513206 yinyong[3233:1042628] (null)-----[ZZYView dealloc]
2017-02-15 13:47:34.513326 yinyong[3233:1042628] ZZZZZ
  • 总结:我们会发现_weakZView根本就没有被添加到self.view上面,在用alloc init分配内存初始化对象之后,这个对象被一个weak型指针_myView弱引用,引用计数为0。 在执行完这句代码 _weakZView = [[ZZYView alloc] initWithFrame:self.view.frame]之后,这个对象就被释放了,也就是说当weak指针指向的对象释放后,weak指针会自动被置空。所以 (null)-----[ZZYView dealloc]ZZZZZ 之前先打印,上面的对zzyText赋值&设置backgroundColor& addSubview都是无效的,这时_weakZView已经为nil。

  • 那我们在用weak前提下,怎么用才能使其成功的添加到self.view上面呢?请看例子2

例子2:

  • 同例子1 类ZZYView的代码不变,我们把控制器ViewController中的代码改成如下:
#import "ViewController.h"
#import "ZZYView.h"

@interface ViewController ()

@property (nonatomic,weak)ZZYView *weakZView;  //弱引用

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    ZZYView *zView = [[ZZYView alloc] initWithFrame:self.view.frame];
    zView.zzyText = @"例子2_weakZView";
    zView.backgroundColor = [UIColor redColor];
    _weakZView = zView;
    [self.view addSubview:_weakZView];
}

#pragma mark点击屏幕触发
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (self.weakZView) {
        [self.weakZView removeFromSuperview];
    }
}

  • 相比例子1我们多了一个强引用的指针myView,并增加了一个touch事件。

  • 总结:由于所有的实例变量和局部变量默认都是strong型指针,所以zView强引用了初始化的对象,而后_weakZView弱引用zView,又通过[self.view addSubview:_weakZView]控制器的subView又强引用了该对象。所以weakZView被成功的添加到self.view上面,并且在“viewDidLoad”这个代码块执行完之后,即使zView被释放了weakZView也没被释放(控制器的subView还强引用着它)。点击屏幕后调用了[self.weakZView removeFromSuperview],weakZView被释放,打印如下

2017-02-15 14:49:41.271127 yinyong[3268:1051053] 例子2_weakZView-----[ZZYView dealloc]

例子3

  • 我们再看看如果用strong会是个什么情况,同例子1 类ZZYView的代码不变,我们把控制器ViewController中的代码改成如下:
#import "ViewController.h"
#import "ZZYView.h"

@interface ViewController ()

@property (nonatomic,strong)ZZYView *strongZView;  //弱引用

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    ZZYView *zView = [[ZZYView alloc] initWithFrame:self.view.frame];
    zView.zzyText = @"例子3_strongZView";
    zView.backgroundColor = [UIColor redColor];
    _strongZView = zView;
    [self.view addSubview:_strongZView];

    /*
     也可以简化这么写
     _strongZView = [[ZZYView alloc] initWithFrame:self.view.frame];
     zView.zzyText = @"例子3_strongZView";
     zView.backgroundColor = [UIColor redColor];
     [self.view addSubview:_strongZView];
     */
}

#pragma mark点击屏幕触发
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (self.strongZView) {
        [self.strongZView removeFromSuperview];
    }
}
  • 总结:strongZView被成功添加到self.view上面,但是和例子2不同的是,点击屏幕后调用了removeFromSuperview,strongZView从界面上移除了不再显示,但strongZView并没被释放。当控制器ViewController被销毁时,触发了ZZYView的dealloc打印了下面的内容。
2017-02-15 14:49:46.271127 yinyong[3268:1051053] 例子3_weakZView-----[ZZYView dealloc]

因为ViewController被销毁,其属性strongZView也被销毁,strongZView指针指向的对象引用计数为0也会被释放。

由上面三个例子可以得出:如果你想让一个控件的生命周期随着你的控制器被销毁才去释放,那就使用strong;如果你仅仅是想让它在被移除之后就被释放,那就使用weak。具体选择用哪个还要看你的需求。一般情况下如果没有特殊需求我们手动创建控件时用的是strong来声明,其用法要比weak简捷并且更不容易出错。当然上面例子中的控件用懒加载的方式会更好,我的下一篇文章就会谈谈自己对其的理解。

你可能感兴趣的:(对手动创建控件时weak&strong的探究)