Block是在栈上生成的,所以一般使用copy方法把Block复制到堆上,避免Block被立刻释放。

Block会对内部的变量形成强引用,而如果同时该变量又持有这个Block,就会导致循环引用而无法释放,从而导致内存泄露。

最常见的就是self持有Block,而又在Block内部调用self的方法或属性,那selfBlock就会形成循环引用而无法释放。由于我们习惯在dealloc中释放对象,但是即使在dealloc中将Block释放也没用,因为selfdealloc根本不会跑进去。比如:

1 self.MyBlock = ^void(){
2
3   [self doSomething];
4 };

其实,最简单的解决方法就是在self的某个非dealloc方法中将Block主动释放,并在需要释放self之前调用这个方法,这样才能有效的解除引用。但是这种方法使用起来比较麻烦,而且很容易忘记调用。

所以我们一般是在Block中使用弱引用的self。下面分别介绍ARCMRC中在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前,需要使用__weakself进行弱引用,并在Block中使用__strongweakSelf进行强引用。

这样做的另一个好处是,在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是一样的。有两处不同:

  1. MRC中使用__block而不是__weak进行弱引用,因为在ARC中使用__block会对该对象进行强引用。

  2. MRCBlock中使用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 的循环引用相关推荐

  1. Block的循环引用详解

    1.首先我们创建了一个网络请求工具类 然后storyboard里面去创建了一个导航控制器 并且把它设置为初始控制器   然后拖入一个bar button  --show--到自带的控制器 这个时候运行 ...

  2. Block的循环引用

    2019独角兽企业重金招聘Python工程师标准>>> 在ios常见的循环引用中曾经提到过block: 看看上面最基本的block循环应用,self包含block,block包含了s ...

  3. ios开发 循环引用 检测_iOS开发——Block引起循环引用的解决方案

    [目前总结了一下,在iOS平台容易引起循环引用的几个场景:一.parent-child模式二.block(编译器会提示警告)三.NSTimer] up vote 0 down vote favorit ...

  4. iOS开发笔记(二):block循环引用

    写这篇文章的缘由是第一次面试时被问到了block循环引用的问题,当时回答的不是很好,首先要明确的是,block是否用copy修饰决定不了循环引用的产生,在此再一次进行补强,有不对的地方还请多多指教. ...

  5. Block循环引用问题(Objective-c)

    造成循环引用的简单理解是:Block的拥有者在Block作用域内部又引用了自己,因此导致了Block的拥有者永远无法释放内存,就出现了循环引用的内存泄漏 示例代码 @interface ObjTest ...

  6. ios block常见的错误(二)——循环引用

    2019独角兽企业重金招聘Python工程师标准>>> 这篇博文继续block的常见错误--循环引用. 循环引用是很多初学者不能察觉的,其产生的原因,是block中的代码会对对象进行 ...

  7. 和block循环引用说再见

    to be block? or to be delegate? 这是一个钻石恒久远的问题.个人在编码中暂时没有发现两者不能通用的地方,习惯上更偏向于block,没有什么很深刻的原因,只是认为block ...

  8. Block 本质、实现原理、内存管理、循环引用、__block等

    一.Block介绍 1.1概念: 将函数及其执行上下文封装起来的对象 底层用struct实现 1.2block实现原理: a .新建项目 代码放入file.m中 b.打开终端cd到项目目录下 c.敲c ...

  9. OC和Swift中循环引用的问题

    总结一下自己对OC中和Swift中循环引用的认识. 一.OC中的循环引用分为类中的循环引用和对象之间的循环引用. 1.类的循环引用 造成原因: 在两个类的.h文件中使用了#import "& ...

最新文章

  1. Junit单元测试需要知道的一些知识点
  2. Failed to load module script: The server responded with a non-JavaScript MIME type of “text/plain“.
  3. 神经网络预测模型算法_MATLAB Elman神经网络的数据预测—电力负荷预测模型研究...
  4. windows+VS2017+opencv4.1.0环境配置
  5. Abp vNext 二进制大对象系统(BLOB)
  6. LightOJ-1220 Mysterious Bacteria (素数打表+欧几里得算法+唯一分解定理)给出x,求x=a^p,最大的指数
  7. document.createElement
  8. Snabbdom(虚拟dom-6-createElm函数)
  9. 高精度测量让交会对接更“温柔”
  10. (90)Verilog HDL系统函数和任务:$fmonitor
  11. 字节跳动副总裁喊话腾讯:停止无理由封杀飞书;Git服务器配置错误导致日产汽车源码泄露;Linux5.10.5 发布
  12. spring cloud构建互联网分布式微服务云平台-Spring Cloud Commons 普通抽象
  13. java static 变量存在哪_Java中的静态方法和静态变量存储在哪里?
  14. 二叉树性质 四种遍历方式
  15. 夺命雷公狗---ECSHOP---01-解决报错问题
  16. Lucene.Net
  17. java8 stream ,filter 等功能代替for循环
  18. tomcat .appcache html5离线缓存,html5 application cache遇到的严重问题
  19. B2B跨境电子商务平台综合服务解决方案
  20. Android 最常用的设计模式四 安卓源码分析——模板方法(Mould)

热门文章

  1. pyghon list指定位置插入字符的方法
  2. 基于灰度的模板匹配算法(一):MAD、SAD、SSD、MSD、NCC、SSDA算法
  3. C++ string 类常用函数
  4. return 函数
  5. opencv矩阵运算(1)
  6. android 延迟2秒执行_每天30秒让你更懂汽车(10自动变速器2执行装置)
  7. 【中文情感分析】SO-PMI算法(HarvestText库的修正以及解析)
  8. C++易于实现的有趣项目【附上完整教程】
  9. Z变换(2020.10.21)
  10. MATLAB格式化输出控制