美文网首页
Block内的强引用

Block内的强引用

作者: 杨淳引 | 来源:发表于2016-12-16 10:05 被阅读51次

    众所周知,当某个对象持有着一个Block的时候,如果在Block内部使用强引用反过来持有这个对象,就会导致引用循环。为了避免引用循环,可以使用__weak修饰符,苹果的官方文档在用代码演示__weak修饰符的时候,有这么一个例子:



      那么,myController持有着completionHander,在completionHander内部又用一个strongMyController反过来去持有myController,这不也是一个引用循环吗?为了探究这个问题,可以用下面的方法来测试一下:

    1、编写一个类ViewController,然后在类内编写方法test,做一个疑似的引用循环:



    2、然后通过一个clang命令将这个类转换成C语言代码:

    clang -x objective-c -rewrite-objc -isysroot
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk
    -fobjc-arc -stdlib=libc++ -mmacosx-version-min=10.7 -fobjc-runtime=macosx-10.7
    -Wno-deprecated-declarations ViewController.m
    

    3、由此可以得到一个cpp文件,将文件中主要的部分提取出来如下:



    4、可以发现:

    • 在Block结构体中看到,被Block捕获的变量是
    ViewController *const __weak weakSelf;
    

    所以Block本身对self的引用仍然只是弱引用,并不造成引用循环。

    • strongSelf只存在于Block对应的函数__ViewController__test_block_func_0里,它的生命周期只在这个函数执行的过程中,函数执行前它不会存在,函数执行完它立刻就被释放了。
    • 所以:
      ①、如果函数执行前self变为nil了,那么函数不会执行,没有任何引用循环发生;
      ②、如果函数执行过程中self变为nil了,那么函数一开始声明的strongSelf会暂时持有着self,此时会有一个暂时的引用循环。当函数执行完(即是Block执行完),strongSelf超出作用域被释放,引用循环从这里开始打破。接下来,由于没有任何强引用持有self了,于是self被释放,最后Block也因为没有任何强引用持有它也被释放了。所有对象就都被顺利释放了。

    所以最终可以确定:苹果的演示代码有可能会造成引用循环,但是只是一个暂时的、可以被打破的引用循环,不会导致内存泄漏。

    相关文章

      网友评论

          本文标题:Block内的强引用

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