分享

Block中weak/strong self的用法

 wintelsui 2018-01-16

在用到block时,我们经常会有这样一种用法

//请忽略不重要的代码行
__weak __typeof(self)weakSelf = self;
blk_t blk = ^() {
    __strong __typeof(weakSelf)strongSelf = weakSelf;
}
  • 1
  • 2
  • 3
  • 4
  • 5

其中比较有意思的地方就是先在block外定义一个弱引用的self指向self,然后在block内定义一个强引用的self指向weakSelf。那么就针对这两点来讲讲block里weak/strong self的问题。首先声明:上面提到的用法很保险,没有什么问题。

weakSelf->self
我们都知道,block比较常见的一个问题就是循环引用问题,简单描述即:self已经持有了block,如果block里再使用self,self将被block截获,然后block持有self,导致循环引用。

那么我们在block外定义一个weakSelf指向self,然后block就会截获这个weakSelf,不会再产生循环引用的问题。

strongSelf->weakSelf
block中还有个有意思的点就是block截获的变量在超出其作用域后仍能使用(比如block截获了self,然后block又被传递到其它地方使用,此时self按理已经释放)。这其实是因为系统会自动的根据情况将block从栈拷贝到堆中并强引用它截获的变量(一般我们的block最开始都是在栈中的),我们知道栈的内存是由系统管理的,而堆是由程序猿管理的,所以实现了变量超出作用域仍能使用。

根据这个说法,我们应该不需要自己强引用weakSelf,我们的weakSelf应该也会被block自己强引用,那我们何必多次一举呢…事实也确实如此,block确实强引用了我们的weakSelf,就算我们不自己强引用weakSelf代码也不会有问题。但是我们在上一段中提到了系统拷贝block是有条件的,有些条件下系统不会自动拷贝block,这种情况下weakSelf超出作用域将被释放。那么哪些情况下系统不会自动copy呢?最常见的一个——block作为参数传递,这也是使用频率非常高的一个点。所以,自己动手是为了更加保险。

下面列出block能够拷贝的情况:
1、调用block的copy方法
2、block作为返回值
3、block赋值时
4、Cocoa框架中方法名中含有usingBlock的方法
5、GCD中

关于GCD中block再提一点:
GCD中的block并没有直接或间接被self强引用的,所以不会存在循环引用,故不需要weakSelf;又GCD中block能够自动copy,所以self超出作用域仍可用,故不需要写strongSelf

总结:
weakSelf是为了解决循环引用
strongSelf是为了保证任何情况下self在超出作用域后仍能够使用

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多