iOS内存话题: 弱引用下的懒加载

阅读下面的内容之前, 你应该知道什么是懒加载, 话句话说就是延时加载.

今天跟大家聊聊对于一个弱引用对象如何使用懒加载, 以及注意事项!

直接上例子.

工程比较简单, 只有一个 ViewController.

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, weak) UIButton *buton;

@end


@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    CGRect rect = CGRectMake(100, 200, 100, 50);
    self.buton.frame = rect;

    [self.view addSubview:self.buton];

    [self.buton addTarget:self
                   action:@selector(changeTheBkc:)
         forControlEvents:UIControlEventTouchUpInside];
}

- (UIButton *)buton
{
    if (nil == _buton) {
        _buton = [UIButton buttonWithType:UIButtonTypeCustom];
        [_buton setTitle:@"我是一个按钮" forState:UIControlStateNormal];
        [_buton setBackgroundColor:[UIColor blueColor]];
    }

    return _buton;
}

- (void)changeTheBkc:(id)sender
{
    UIColor *color = [UIColor redColor];
    [self.buton setBackgroundColor:color];
}
@end

大家可以看到, UIButton 对象 buton 是一个 weak 的引用.

你会说, 这个没有什么特殊的, 运行效果一定是一个按钮贴在视图上面.

就像下面这个样子.

图1

其实, 运行起来, 你会发现, 屏幕一片空白.

好了, 我们来分析一下原因吧!

改造一下 viewDidload 方法

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    CGRect rect = CGRectMake(100, 200, 100, 50);
    self.buton.frame = rect;

    NSLog(@"--------1--------sel.button: %@", _buton);

    [self.view addSubview:self.buton];

    NSLog(@"--------2--------sel.button: %@", _buton);

    [self.buton addTarget:self
                   action:@selector(changeTheBkc:)
         forControlEvents:UIControlEventTouchUpInside];

    NSLog(@"--------3--------sel.button: %@", _buton);
}

打印结果也许让你兴奋

图2

弱引用的对象, 在使用完成(懒加载的方法中, 即其 get 方法), 被系统回收了.

这个时候, 你也许想到, 把这个对象改为 strong 不就行了吗?

是的, 可以这么干.

但是, 我想说, 还有一种方式, 如果你以前经历过 MRC 的编码, 可能会很快明白其中的原理.

接下来, 我们修改一下懒加载的代码.

- (UIButton *)buton
{
    if (nil == _buton) {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        [btn setTitle:@"按钮" forState:UIControlStateNormal];
        [btn setBackgroundColor:[UIColor blueColor]];

        [self.view addSubview:btn];

        _buton = btn;
    }

    return _buton;
}

在 viewDidload 中, 修改一下代码

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    CGRect rect = CGRectMake(100, 200, 100, 50);
    self.buton.frame = rect;

    NSLog(@"--------1--------sel.button: %@", _buton);

    [self.buton addTarget:self
                   action:@selector(changeTheBkc:)
         forControlEvents:UIControlEventTouchUpInside];

    NSLog(@"--------2--------sel.button: %@", _buton);
}

运行, 可以看到效果了, 一个蓝色的 UIButton 在那里 出现了.

到这里, 唯一一个疑惑就是, 这里为毛显示了~

大家, 应该注意到这句 code

[self.view addSubview:btn];

这里, 临时对象 btn 在 addSubview 的时候, 被 retain 一次, 所以赋值给 buton, 系统就不会回收了!

©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页