关于Block使用的二三事

引子

我们今天不讲Block这个语法,因为作为一个合格的开发者,如果你不知道,那么实在是说不过去。接下来我就当大家都知道了,如果确实不懂,建议先去看资料吧。

Block最主要的一个注意事项,就是retain cycle(循环引用问题),这会直接导致内存问题。一般的处理方式就是在block内使用weak 作为self指针的引用。这样block内就不会出现对self的强引用。

1. weakSelf和strongSelf的使用

请看下面这段代码

__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
    __strong __typeof(weakSelf)strongSelf = weakSelf;

    strongSelf.networkReachabilityStatus = status;
    if (strongSelf.networkReachabilityStatusBlock) {
        strongSelf.networkReachabilityStatusBlock(status);
    }

};

这段代码来自于大家非常熟悉的AFNetwork框架中,功能是监测网络的,当然这个不是主要点。大家来看语法。

  1. 首先在block的最外层,定义一个weakSelf
  2. 在block在定义一个strongSelf,形成对weakSelf的引用,类型是__strong
  3. 在block内多次使用strongSelf 调用函数
原因

估计有的朋友都没想到还需要用strongSelf。这么写的原因就在于,如果在block内多次使用weakSelf进行调用函数或者实例变量,有可能会造成某一次调用的过程中weakSelf已经失效。例子

__weak __typeof__(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [weakSelf do1];
    [weakSelf do2];
});

do2在执行的过程中可能已经被释放,失效了。

2. block都会产生retain circle吗

答案是No,首先大家要理解retain circle产生的原因:A持有B,B持有A,依据OC的引用计数retain、release规则,双方各自被对方持有,谁也无法正常释放,循环引用就产生了。

A 
...
-(void)dealloc{
    [B release];
    [super dealloc]; 
}
B 
...
-(void)dealloc{
    [A release];
    [super dealloc]; 
}

上面的代码一目了然,释放A必须先释放B,但是B的dealloc中又需要释放A,谁也跑不掉了。

回到正题

[UIView animateWithDuration:duration animations:^{
            [self.superview layoutIfNeeded]; 
 }]; 

这种只是block内引用了self,单向引用,不会产生retain circle,大胆的使用self。
</br>

dispatch_async(dispatch_get_main_queue(), ^{
  self.headerImageView = image;
});

dispatch_async不知道self什么时候释放,因此在调用的时候,先retain self一次,等到代码执行结束,在调用release,因此实际上并没有增加self的引用计数,也不需要担心retain circle。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容