美文网首页
对手动创建控件时weak&strong的探究

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

作者: 木格措的天空 | 来源:发表于2017-02-15 17:32 被阅读113次
    • 本文乃己之拙见,欢迎指正,转载请注明出处。

    例子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<UITouch *> *)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<UITouch *> *)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的探究

          本文链接:https://www.haomeiwen.com/subject/ujuqwttx.html