Block内的强引用

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

Block内的强引用

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

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

Block内的强引用

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文件,将文件中主要的部分提取出来如下:

Block内的强引用

4、可以发现:

(1)、在Block结构体中看到,被Block捕获的变量是

ViewController *const __weak weakSelf;

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

(2)strongSelf只存在于Block对应的函数__ViewController__test_block_func_0里,它的生命周期只在这个函数执行的过程中,函数执行前它不会存在,函数执行完它立刻就被释放了。

(3)所以:

如果函数执行前self变为nil了,那么函数不会执行,没有任何引用循环发生;

如果函数执行过程中self变为nil了,那么函数一开始声明的strongSelf会暂时持有着self,此时会有一个暂时的引用循环。当函数执行完(即是Block执行完),strongSelf超出作用域被释放,引用循环从这里开始打破。接下来,由于没有任何强引用持有self了,于是self被释放,最后Block也因为没有任何强引用持有它也被释放了。所有对象就都被顺利释放了。

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

 

原文链接: https://www.cnblogs.com/shayneyeorg/p/6185898.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    Block内的强引用

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/245929

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 上午1:11
下一篇 2023年2月14日 上午1:11

相关推荐