众所周知,当某个对象持有着一个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、可以发现:

(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也因为没有任何强引用持有它也被释放了。所有对象就都被顺利释放了。

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

Block内的强引用的更多相关文章

  1. 避免Block中的强引用环

    [避免Block中的强引用环] In manual reference counting mode, __block id x; has the effect of not retaining x. ...

  2. IOS block 对象强引用和若引用

    1. 在block外面这样:__weak MyController *weakSelf = self 或者 __weak __typeof(self) weakSelf = self;是为了防止强引用 ...

  3. 弱引用?强引用?未持有?额滴神啊-- Swift 引用计数指导

    ARC ARC 苹果版本的自动内存管理的编译时间特性.它代表了自动引用计数(Automatic Reference Counting).也就是对于一个对象来说,只有在引用计数为0的情况下内存才会被释放 ...

  4. Swift-08-闭包引起的循环强引用

    循环强引用还会发生在当你将一个闭包赋值给类实例的某个实例,并且这个闭包体中又实用了这个类实例.这个闭包体重可能访问了实例的某个属性,例如self.**,或者闭包中调用了实例的某个方法,例如self.* ...

  5. 关于C语言中的强符号、弱符号、强引用和弱引用的一些陋见,欢迎指正

    首先我表示很悲剧,在看<程序员的自我修养--链接.装载与库>之前我竟不知道C有强符号.弱符号.强引用和弱引用.在看到3.5.5节弱符号和强符号时,我感觉有些困惑,所以写下此篇,希望能和同样 ...

  6. 浅谈C语言中的强符号、弱符号、强引用和弱引用

    摘自http://www.jb51.net/article/56924.htm 浅谈C语言中的强符号.弱符号.强引用和弱引用 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2014- ...

  7. Java -强引用&弱引用

    ⑴强引用(StrongReference) 就是通过new得的对象引用 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java虚拟机宁愿抛出OutOfMe ...

  8. 用block解决nstimer循环引用

    大多数开发者可能都会这样来实现定时器.创建定时器的时候,由于目标对象是self,所以要保留此实例.然而,因为定时器是用实例变量存放的,所以实例也保留了定时器,这就造成了循环引用.除非调用stop方法, ...

  9. ios NSTimer的强引用问题

    在一个controller中,使用 NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest ...

随机推荐

  1. (转)Android创建桌面快捷方式两种方法

    [IT168技术]Android在桌面上生成快捷方式有两种情况,一种是直接在桌面直接生成;一种是长按桌面,在弹出的快捷菜单中生成. 谈谈在桌面上直接生成.个人觉得这个比较爽快,既然都是快捷方式了干嘛还 ...

  2. cobol语言基础培训教程

    COBOL 是Common Business Oriented Language 的缩写.它不仅是商业数据处理的理想语言,而且广泛用于数据管理领域,因此COBOL 语言也被称为”用于管理的语言”. 一 ...

  3. EBS-PAC成本更新事务处理

     PAC成本更新事务处理 DECLARE   l_itfs_rec mtl_transactions_interface% ROWTYPE; BEGIN   --插入接口表   SELECT mt ...

  4. DB2数据库全系列版本安装介质下载地址

    网盘:http://pan.baidu.com/s/1qWE4D7A? ... qq-pf-to=pcqq.group官方:http://www-01.ibm.com/support/docview. ...

  5. (转)Javascript面向对象编程(二):构造函数的继承(作者:阮一峰)

    对象之间的"继承"的五种方法. 比如,现在有一个"动物"对象的构造函数. function Animal(){ this.species = "动物& ...

  6. await与async的简单了解

    异步方法的返回类型可以为Task.Task.void.方法不能声明ref或out参数. 无法捕捉返回类型为void的异步方法引发的异常,如果返回Task或Task的异步方法中出现异常,则在任务等待时将 ...

  7. 注意:"AspNetPager”的控件“AspNetPager1”必须放在具有 runat=server 的窗体标记内

    应加: <form id="form1" runat="server"> </form> 否则一开始什么也不显示,页面控件看不见,加上a ...

  8. SQL Server2008知识点总结

    1.SQL Server2008基本服务及功能 2.管理SQL Server2008安全:登录.权限.数据库用户.管理角色.服务器角色.管理数据库角色. 3.数据库管理.表管理(临时表和系统表.列值属 ...

  9. Java学习笔记——可视化Swing中JTable控件绑定SQL数据源的两种方法

    在 MyEclipse 的可视化 Swing 中,有 JTable 控件. JTable 用来显示和编辑常规二维单元表. 那么,如何将 数据库SQL中的数据绑定至JTable中呢? 在这里,提供两种方 ...

  10. HDU 4612 (13年多校第二场1002)无向图缩点,有重边

    这道题是多校的题,比赛的时候是一道纷纷水过的板刷题. 题意:给你一些无向边,只加一条边,使该图的桥最少,然后输出最少的桥. 思路:当时大致想到思路了,就是缩点之后找出最长的链,然后用总的桥数减去链上的 ...