BLock的内存泄露

  在我们代码中关于block的使用可以说随处可见,第一次接触block的时候是关于UIView的块动画,那时觉得block的使用好神奇,再后来分析总结为block其实就是一个c语言函数,只是我们可以在任意处调用此函数。有了这样的理解我开始经常使用block。在做项目以后发现使用block竟然会引起内存泄露,于是开始自己调试研究block的内存管理问题。

普通的block使用(包括块动画)

这里有一个简单的block使用,在里面我们可以添加任何自己想进行的操作,大部分的使用也是如此

 void (^Block)(int) = ^(int num){
//此处还可添加其他代码 ....
NSLog(@"int number is %d",num);
};

包括UIView的块动画也是如此使用,在这里我们定义了一个图像视图的位置及透明度的变化

 [UIView animateWithDuration:2.0 animations:^(void){
smallImage.frame = CGRectMake(, , , );
} completion:^(BOOL finished) {
smallImage.alpha = ;

这些block操作中,我一直都认为block中的对象会在block使用后就被释放(但UIView的操作好像是这么做的)

block内存管理初现

  直到我在项目中遇见这样一个情况:我设置有2个控制器first及second,其中second中包含一个block对象,而block的实现是在first中实现(一般的block传值都是这么做)。而界面的推送是由first控制器push出second控制器。但当我second控制器pop的时候,问题出现second控制器不走delloc方法,即pop后second控制器还存在没有被销毁(因为当时要做delloc中做一些操作,才发现这个问题)!block示例代码如下:

first控制器中block的实现

 SecondViewController *secondVC = [[SecondViewController alloc] init];
secondVC .block = ^(NSString *text){
self.text = secondVC.text;
};

  这么一个简单的传值block使用,居然能引起second控制器无法释放,于是研究其原理,并网上搜索资料,得出一个结论:second控制器在block中被持有一次才导致其无法释放。因为block本质上是一个函数,而编译器不知道你什么时候会调用block里面的值,所以为了确保编译器内secondVC不会被释放,编译器会自动对其进行一次持有(在自身类中使用block方法操作自身的成员属性也会使自己的引用计算加1,造成无法释放)。

其解决办法也简单 在外部添加一个弱引用对象指向需要在block中操作的对象,即__weak typeof(对象名) 别名= 对象名;

 SecondViewController *secondVC = [[SecondViewController alloc] init];
__weak typeof(secondVC) second = secondVC;
__weak typeof(self) vc = self;
secondVC .block = ^(NSString *text){
vc.text = second.text;
};

这样就能够有效的防止block使用引起的内存泄露问题。

NSTimer使用问题

另外在还在项目中遇见一个关于NSTimer的使用问题。我们想到在控制器销毁时同时停止NSTimer并置为nil

 -(void)dealloc {
[self.timer invalidate];
self.timer = nil;
NSLog(@"%@ dealloc", NSStringFromClass([self class]));
}

然而控制器被pop后并没有走此方法(又是内存泄露),由于之前出现了Block内存泄露的问题,我就想是不是因为这个_timer加载的时候对self进行了一次持有

_timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerUp:) userInfo:nil repeats:YES];

进行调试测验,果然是这里出了问题,因为其对控制器持有了一次。于是我想到既然这样那我干脆就在viewWillDisappear()中做个判断,如果是pop控制器,我就先设置[self.timer invalidate]操作这样控制器就会走dealloc()方法。后来再网上找资料发现了一个更简单的解决办法,即同Block的内存管理一样使用弱引用对象

 __weak typeof(self) vc = self;
_timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:vc selector:@selector(timerUp:) userInfo:nil repeats:YES];

这样的解决办法就要比我之前的要简单多了,唯一需要注意的就是此处vc的作用域!

项目问题总结:Block内存泄露 以及NSTimer使用问题的更多相关文章

  1. ARC下的内存泄露

    iOS提供了ARC功能,很大程度上简化了内存管理的代码. 但使用ARC并不代表了不会发生内存泄露,使用不当照样会发生内存泄露. 下面列举两种ARC导致内存泄露的情况. 1,循环参照 A有个属性参照B, ...

  2. 实战Go内存泄露【转】

    最近解决了我们项目中的一个内存泄露问题,事实再次证明pprof是一个好工具,但掌握好工具的正确用法,才能发挥好工具的威力,不然就算你手里有屠龙刀,也成不了天下第一,本文就是带你用pprof定位内存泄露 ...

  3. 使用MLeaksFinder检测项目内存泄露总结

    前几天看到开源工具MLeaksFinder,决定用在公司的项目中试一下,效果很不错,用法也很简单,直接把项目文件夹拖到项目中就可以了,依靠这个项目,我发现公司项目中有不少内存泄露的地方,在此总结一下: ...

  4. 浅析NSTimer & CADisplayLink内存泄露

    偶得前言 NSRunLoop与定时器 - invalidate的作用 我们如何解决? 偶得前言 本篇文章中我们主要谈谈NSTimer\CADisplayLink在使用过程中牵扯到内存泄露的相关问题及解 ...

  5. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  6. Block产生的内存泄露,以及解决方法

    前言: 在ARC(自动引用技术)前,Objective-c都是手动来分配释放 释放 计数内存,其过程非常复杂. ARC技术推出后,貌似世界和平了很多,但是其实ARC并不等同于Java或者C#中的垃圾回 ...

  7. 关于block的回调使用-防止内存泄露问题

    block 一般用于回调,比方请求数据我们把asi封装好,仅仅用block调数据就方便很多 获取到得数据假设要给之加入数据,切记不能够使用self.(这个数组) 或者_(这个数组) addObject ...

  8. 关于 Unity 项目中的 Mono 堆内存泄露

    关于 Unity 项目中的 Mono 堆内存泄露 题记:这是补一篇应该在将近一年前就应该写的记录,今天终于补上. 内存泄露是一个老话题了,之前我专门写过一篇 排查 Lua 虚拟机内存泄露 的文章,并且 ...

  9. 利用内存分析工具(Memory Analyzer Tool,MAT)分析java项目内存泄露

    转载:http://blog.csdn.net/wanghuiqi2008/article/details/50724676 一.开发环境: 操作系统:ubuntu 14.04 IDE:Eclipse ...

随机推荐

  1. Linux用户组与用户组基本命令

    1.添加用户组:groupadd sexy2.修改组名:groupmod -n market sexy3.修改组编号:groupmod -g 668 market4.添加有编号的用户组:group - ...

  2. jquery闭包的使用

    <div id="divTest"> Test </div> <br /> <hr /> <div id="divT ...

  3. 使用存储过程来动态调用数据(SELECT)

    USE [MyTestDb] GO /****** Object: StoredProcedure [dbo].[PROC_GetChannelList] Script Date: 04/09/201 ...

  4. Oracle连接字符串C#

    Password=密码;User ID=ID;Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = ...

  5. 基于@AspectJ和schema的aop(四)---@AspectJ进阶

    @AspectJ可以使用切点函数定义切点, 我们还可以使用逻辑运算对切点进行复合运算得到复合的切点. 我们还可以对切点进行命名, 从而可以复用切点.当一个连接点匹配多个切点时, 需要考虑增强织入的顺序 ...

  6. kindeditor编辑器

    一 简单使用方法 1. 把所有文件上传到程序所在目录下,例如:http://你的域名/editor/. 2. 在此目录下创建attached文件夹,并把权限改成777. 3. 要添加编辑器的地方加入以 ...

  7. 2016-2017 CT S03E05: Codeforces Trainings Season 3 Episode 5 (2016 Stanford Local Programming Contest, Extended) J

    链接:http://codeforces.com/gym/101116 题意:给出n个点,要求一个矩形框将(n/2)+1个点框住,要面积最小 解法:先根据x轴选出i->j之间的点,中间的点(包括 ...

  8. WPFのTopMost属性的应用

    最近做一个东西,需要用到多个子窗体层级关系,首先,有一个MainWindow,然后有一个win1和win2甚至更多,我需要达到的控制是,win1选为focus的时候,win2在win1的上面,TopM ...

  9. 【Javascript】列表查询页面,简单地保存上一次查询的查询参数

    开发中经常做一些查询参数 + 列表参数的功能,这些功能有时候需提供导出Excel,或带超链接到其他明细页面的功能点. 在一些交互性要求严格的系统,需求方会要求: 用户第一个输入某些查询条件进行列表查询 ...

  10. 一个Public的字段引起的,谈谈继承中的new

    一直觉得对c#面向对象这块已经掌握的很好了,因为正常情况下字段一般我们设计成私有的,今天突然想到一个实验,如下有两个很简单的类: public class Farther { ; public vir ...