Block 的循环引用
Block
是在栈上生成的,所以一般使用copy
方法把Block
复制到堆上,避免Block
被立刻释放。
Block
会对内部的变量形成强引用,而如果同时该变量又持有这个Block
,就会导致循环引用而无法释放,从而导致内存泄露。
最常见的就是self
持有Block
,而又在Block
内部调用self
的方法或属性,那self
和Block
就会形成循环引用而无法释放。由于我们习惯在dealloc
中释放对象,但是即使在dealloc
中将Block
释放也没用,因为self
的dealloc
根本不会跑进去。比如:
1 self.MyBlock = ^void(){ 2 3 [self doSomething]; 4 };
其实,最简单的解决方法就是在self
的某个非dealloc
方法中将Block
主动释放,并在需要释放self
之前调用这个方法,这样才能有效的解除引用。但是这种方法使用起来比较麻烦,而且很容易忘记调用。
所以我们一般是在Block
中使用弱引用的self
。下面分别介绍ARC
和MRC
中在Block
中使用弱引用self
的方法。
ARC
1 __weak typeof(self) weakSelf = self; 2 3 self.MyBlock = ^void(){ 4 5 __strong typeof(self) strongSelf = weakSelf; 6 7 [strongSelf doSomething]; 8 };
这样做的好处是不必在Block
直接使用self
,这样就不会对self
进行强引用,只要self
需要释放,self
就会自动释放,Block
也会自动释放。在ARC
中,进入Block
前,需要使用__weak
对self
进行弱引用,并在Block
中使用__strong
对weakSelf
进行强引用。
这样做的另一个好处是,在ARC
中使用__weak
之后,如果self
在某个地方被释放了,那weakSelf
也会被自动置为nil
,这样即使在Block
中使用weakSelf
,也不会访问错误。
而在Block
中使用__strong
则是为了避免在使用Block
的过程中self
被释放导致访问出错。
MRC
1 __block typeof(self) blockSelf = self; 2 3 self.MyBlock = ^void(){ 4 5 if (!malloc_zone_from_ptr(blockSelf)) 6 return; 7 8 __strong typeof(self) strongSelf = blockSelf; 9 10 [strongSelf doSomething]; 11 };
其实,MRC
的基本思路和ARC
是一样的。有两处不同:
在
MRC
中使用__block
而不是__weak
进行弱引用,因为在ARC
中使用__block
会对该对象进行强引用。在
MRC
的Block
中使用malloc_zone_from_ptr()
方法判断blockSelf
是否已经被释放,因为MRC
不会对已释放的对象自动置为nil
。
可见,无论是MRC
还是ARC
,解决方法都是类似的。虽然Block
的使用增加了简洁性和便利性,但使用Block
的过程中也要时刻注意避免内存泄露。
How Do I Declare A Block in Objective-C? 总结了声明Block
的几种格式,在开发过程中可以参考使用。
转载于:https://www.cnblogs.com/coltfoal/p/4763540.html
Block 的循环引用相关推荐
- Block的循环引用详解
1.首先我们创建了一个网络请求工具类 然后storyboard里面去创建了一个导航控制器 并且把它设置为初始控制器 然后拖入一个bar button --show--到自带的控制器 这个时候运行 ...
- Block的循环引用
2019独角兽企业重金招聘Python工程师标准>>> 在ios常见的循环引用中曾经提到过block: 看看上面最基本的block循环应用,self包含block,block包含了s ...
- ios开发 循环引用 检测_iOS开发——Block引起循环引用的解决方案
[目前总结了一下,在iOS平台容易引起循环引用的几个场景:一.parent-child模式二.block(编译器会提示警告)三.NSTimer] up vote 0 down vote favorit ...
- iOS开发笔记(二):block循环引用
写这篇文章的缘由是第一次面试时被问到了block循环引用的问题,当时回答的不是很好,首先要明确的是,block是否用copy修饰决定不了循环引用的产生,在此再一次进行补强,有不对的地方还请多多指教. ...
- Block循环引用问题(Objective-c)
造成循环引用的简单理解是:Block的拥有者在Block作用域内部又引用了自己,因此导致了Block的拥有者永远无法释放内存,就出现了循环引用的内存泄漏 示例代码 @interface ObjTest ...
- ios block常见的错误(二)——循环引用
2019独角兽企业重金招聘Python工程师标准>>> 这篇博文继续block的常见错误--循环引用. 循环引用是很多初学者不能察觉的,其产生的原因,是block中的代码会对对象进行 ...
- 和block循环引用说再见
to be block? or to be delegate? 这是一个钻石恒久远的问题.个人在编码中暂时没有发现两者不能通用的地方,习惯上更偏向于block,没有什么很深刻的原因,只是认为block ...
- Block 本质、实现原理、内存管理、循环引用、__block等
一.Block介绍 1.1概念: 将函数及其执行上下文封装起来的对象 底层用struct实现 1.2block实现原理: a .新建项目 代码放入file.m中 b.打开终端cd到项目目录下 c.敲c ...
- OC和Swift中循环引用的问题
总结一下自己对OC中和Swift中循环引用的认识. 一.OC中的循环引用分为类中的循环引用和对象之间的循环引用. 1.类的循环引用 造成原因: 在两个类的.h文件中使用了#import "& ...
最新文章
- Junit单元测试需要知道的一些知识点
- Failed to load module script: The server responded with a non-JavaScript MIME type of “text/plain“.
- 神经网络预测模型算法_MATLAB Elman神经网络的数据预测—电力负荷预测模型研究...
- windows+VS2017+opencv4.1.0环境配置
- Abp vNext 二进制大对象系统(BLOB)
- LightOJ-1220 Mysterious Bacteria (素数打表+欧几里得算法+唯一分解定理)给出x,求x=a^p,最大的指数
- document.createElement
- Snabbdom(虚拟dom-6-createElm函数)
- 高精度测量让交会对接更“温柔”
- (90)Verilog HDL系统函数和任务:$fmonitor
- 字节跳动副总裁喊话腾讯:停止无理由封杀飞书;Git服务器配置错误导致日产汽车源码泄露;Linux5.10.5 发布
- spring cloud构建互联网分布式微服务云平台-Spring Cloud Commons 普通抽象
- java static 变量存在哪_Java中的静态方法和静态变量存储在哪里?
- 二叉树性质 四种遍历方式
- 夺命雷公狗---ECSHOP---01-解决报错问题
- Lucene.Net
- java8 stream ,filter 等功能代替for循环
- tomcat .appcache html5离线缓存,html5 application cache遇到的严重问题
- B2B跨境电子商务平台综合服务解决方案
- Android 最常用的设计模式四 安卓源码分析——模板方法(Mould)