美文网首页
深刻理解block的循环引用

深刻理解block的循环引用

作者: SevenOrange | 来源:发表于2018-05-15 17:49 被阅读0次

    最近再次提到block循环引用的问题,因此在此做一个梳理。大致罗列下接下来的思路:

    1.循环引用怎么产生的?

    要想解决循环引用的问题,先要了解循环引用如何产生的。

    简单来说就是在堆上的对象与堆上的对象互相引用造成的环,就会引起循环引用。

    听上去很拗口,不过这个概念很重要。

    2.oc中block在内存中是存放在什么位置?堆?栈?

    接下来再看oc中的三种block

    1.NSConcreteGlobalBlock

    全局block,存储在数据区,不会引起循环引用的问题。(因为没有捕获外部变量)

    2.NSConcreteStackBlock

    存储在栈上的block,内存管理由系统处理,不会引起循环引用问题

    3.NSConcreteMallocBlock

    这种block在堆上,如果捕获了外部对象,则会引起循环引用的问题。

    3.关键字__block 、__weak、__strong的作用

    __block 修饰的变量可以在block中被修改,具体实现细节很多大神都有讲解,各位同学可以先去看看内部原理,这里主要讲__weak、__strong在使用中的细节

    注意:在ARC下,只要将block赋值给一个变量,那么这个block就将被拷贝到堆上,这是编译器的优化。所以,这种情况下,block被强引用,block又对捕获的对象强引用,我们就必须使用__weak来打破循环

    __weak大家都很熟悉,对对象弱引用,以打破引用循环,解决问题。

    但是使用__weak有一个问题,可能导致在block执行的过程中对象被释放了,这就是一个很严重的问题,如果在block之前被释放,还可以接受。下面看一个例子:

    这里可以看到,在执行block的时候,p被意外的释放了。

    被提前意外释放

    如上图:在block执行期间,Person对象p被释放了,导致同一个block中代码前后执行的结果不一样。所以我们必须再在block中使用__strong来对p进行一次抢占,这样做的好处在于,在执行到block的时候,能够保证在block执行期间,对象都一直存在。如图:

    __strong保证了在block执行周期对象都一直存在

    如上图:使用了__strong保证了block执行时,如果对象没有被释放,那么整个块中都不会被释放


    总结:为了避免循环引用,同时为了防止异步的block在回调的时,block执行的过程中被意外释放,我们使用__strong 对block外的__weak对象再次强引用,既能够防止引用循环,又能够保证代码的正确执行。

    相关文章

      网友评论

          本文标题:深刻理解block的循环引用

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