iOS技术分享iOSiOS Developer

iOS的weakSelf与strongSelf

2017-05-17  本文已影响522人  踏云小子

避免循环引用的标准做法:weakSelf+strongSelf

假设我们的类有一个属性叫做 model, 我们想要当 model 中的 data 变化的时候,有一个 label 的 text 会随之改变,为了达到这目的,我们设置 model :

- (void)setUpModel{
    XYModel *model = [XYModel new];
   
    model.dataChanged = ^(NSString *title) {
        self.titleLabel.text = title;                
    };
   
    self.model = model;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    printf("retain count:%ld\n", CFGetRetainCount((__bridge CFTypeRef)(self)));
    
    [self setUpModel];
    
    printf("retain count:%ld\n", CFGetRetainCount((__bridge CFTypeRef)(self)));
}

果然,打印显示,引用计数+1了

image.png

为啥?我们的 ViewController 持有了 model , model 持有了一个 Block , 这个 Block 又持有了 ViewController ,导致了循环引用。so通过添加 _weak 和 _strong 修饰的变量来打破循环引用,代码如下:

- (void)setUpModel{
    XYModel *model = [XYModel new];
   
    __weak typeof(self) weakSelf = self;
    model.dataChanged = ^(NSString *title) {
        __strong typeof(self) strongSelf = weakSelf;
        strongSelf.titleLabel.text = title;   
    };
    
    self.model = model;
}

果然,效果很理想

image.png

为什么要用strongSelf

其实大家可以试一下,直接用weakSelf,你会发现引用计数不变,那为啥要加这玩意儿,难道为了装逼?!主要是有时候weakSelf在block里在执行doSomething还存在,但在执行doMorething前,可能会被释放了,故为了保证self在block执行过程里一直存在,对他强引用strongSelf,一句话的事情

- (void)setUpModel{
    XYModel *model = [XYModel new];
   
    __weak typeof(self) weakSelf = self;
    model.dataChanged = ^(NSString *title) {
        [weakSelf doSomething];        
        [weakSelf doMore];                
    };
    
    self.model = model;
}

如果出现双层block嵌套甚至更多怎么办😰

看下面的例子,出现了两个block

- (void)setUpModel{
    XYModel *model = [XYModel new];
   
    __weak typeof(self) weakSelf = self;
    model.dataChanged = ^(NSString *title) {
        __strong typeof(self) strongSelf = weakSelf;
        strongSelf.titleLabel.text = title;
                      
        strongSelf.model.dataChanged = ^(NSString *title2) {
            strongSelf.titleLabel.text = title2;
        };        
    };
    
    self.model = model;
}

结果引用计数+1了,shit,我们还需要对strongSelf再进行一次weakSelf-strongSelf
,如下

- (void)setUpModel{
    XYModel *model = [XYModel new];
   
    __weak typeof(self) weakSelf = self;
    model.dataChanged = ^(NSString *title) {
        __strong typeof(self) strongSelf = weakSelf;
        strongSelf.titleLabel.text = title;
        
        __weak typeof(self) weakSelf2 = strongSelf;
        strongSelf.model.dataChanged = ^(NSString *title2) {
            __strong typeof(self) strongSelf2 = weakSelf2;
            strongSelf2.titleLabel.text = title2;
        };
    };
    
    self.model = model;
}

这样,就避免的引用循环,总结一下,不管都多少个block嵌套,皆按此法

更装逼的写法weakify + strongify

weakify 和 strongify其实是这样:

#define weakify(var) __weak typeof(var) XYWeak_##var = var;
#define strongify(var) \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wshadow\"") \
__strong typeof(var) var = XYWeak_##var; \
_Pragma("clang diagnostic pop")
\\define加入反斜杠\表示换行意思

具体按下面使用:

- (void)setUpModel{
    XYModel *model = [XYModel new];
   
    weakify(self);
    model.dataChanged = ^(NSString *title) {
        strongify(self);
        self.titleLabel.text = title;   
    };
    
    self.model = model;
}

以上代码翻译下:

- (void)setUpModel{
    XYModel *model = [XYModel new];
   
    __weak typeof(self) XYWeak_self = self;
    model.dataChanged = ^(NSString *title) {
        __strong typeof(self) self = XYWeak_self;
        self.titleLabel.text = title;   
    };
    
    self.model = model;
}
上一篇 下一篇

猜你喜欢

热点阅读