内存泄漏的常见场景

CF类型内存

注意以create,copy作为关键字的函数都是需要释放内存的,注意配对使用。比如:CGColorCreate<-->CGColorRelease

MRC内存使用

这部分不做详细介绍,也是注意配对使用,需要说明的是,如果代码中有部分文件是MRC的,在已有文件中加代码的时候注意一下,不能都按照ARC的方式处理。

ARC内存使用

ARC已经为我们做了很多封装,我们不必再显示的调用retain,release,但是还是要注意循环引用的场景。
在此,常规的对象间的互相引用和block的循环引用大家都比较了解,这里就不赘述了,罗列几个我们代码中的错误。

1. NSTimer

NSTimer会造成循环引用,timer会强引用target即self,一般self又会持有timer作为属性,这样就造成了循环引用。
那么,如果timer只作为局部变量,不把timer作为属性呢?同样释放不了,因为在加入runloop的操作中,timer被强引用。而timer作为局部变量,是无法执行invalidate的,所以在timer被invalidate之前,self也就不会被释放。
所以我们要注意,不仅仅是把timer当作实例变量的时候会造成循环引用,只要申请了timer,加入了runloop,并且target是self,虽然不是循环引用,但是self却没有释放的时机。如下方式申请的定时器,self已经无法释放了。

NSTimer *timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(commentAnimation) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

解决这种问题有几个实现方式,大家可以根据具体场景去选择:

  • 增加startTimer和stopTimer方法,在合适的时机去调用,比如可以在viewDidDisappear时stopTimer,或者由这个类的调用者去设置。
  • 每次任务结束时使用dispatch_after方法做延时操作。注意使用weakself,否则也会强引用self。
- (void)startAnimation
{WS(weakSelf);dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{[weakSelf commentAnimation];});
}
  • 使用GCD的定时器,同样注意使用weakself。
WS(weakSelf);
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{[weakSelf commentAnimation];
});
dispatch_resume(timer);

2. NSNotification

使用block的方式增加notification,引用了self,在删除notification之前,self不会被释放,与timer的场景类似,其实这段代码已经声明了weakself,但是调用_eventManger方法还是引起了循环引用。
也就是说,即使我们没有调用self方法,_xxx也会造成循环引用。

[[NSNotificationCenter defaultCenter] addObserverForName:kUserSubscribeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {if (note) {Model *model=(Model *)note.object;if ([model.subId integerValue] == [weakSelf.subId integerValue]) {[_eventManger playerSubsciption:NO];}}
}

3. __block

__blockMRC中是不会增加引用的,可是在ARC中会增加,所以在ARC中,只能使用__weak去打破循环引用。

__block MyViewController *weaksef = self;
_myViewController.editBlock = ^(){[weaksef refreshUI];
};

另外声明一点,并非所有的block都需要使用weak来打破循环引用,如果self没有持有block就不会造成循环引用(例如, 动画block块)。而有些地方之所以使用了__weak,是为了在[self dealloc]之后就不再执行了。在这种场景下使用weakself时,也需要注意,如果self被释放了会不会引起异常。比如下面这段代码把weakself取到的值作为入参,如果self释放了,传nil,引起crash:

[[HttpCore sharedInstance] getRequestWithPath:url target:self params:params success:^(NSDictionary *result, NSURLRequest *request, NSHTTPURLResponse *response) {} failure:^(NSError *error) {dispatch_group_leave(weakSelf.startGroup);}];

4.performSelector内存泄露

performSelector延时调用的问题,

performSelector关于内存管理的执行原理是这样的:执行 [self performSelector:@selector(method1:) withObject:self afterDelay:3]; 的时候,系统会将self的引用计数加1,执行完这个方法时,还会将self的引用计数减1,当方法还没有执行的时候,要返回父视图释放当前视图的时候,self的计数没有减少到0,而导致无法调用dealloc方法,出现了内存泄露。

所以最后我的解决办法就是取消那些还没有来得及执行的延时函数,代码很简单:

[NSObject cancelPreviousPerformRequestsWithTarget:self]

当然你也可以一个一个得这样用:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(method1:) object:nil]

加上了这个以后,dealloc方法就会被调用,问题解决!

为了安全还是

1.调用performa之前先单个取消一下

2.弹出viewcontroller单个取消一下

3. 还有 一些特殊情况业务操作需要过几秒,是不要取消,比如要保存一些数据。

iOS 内存泄漏的常见场景相关推荐

  1. iOS内存泄漏的常见情况

    2019独角兽企业重金招聘Python工程师标准>>> 声明delegate为strong类型,简而言之,如果父VC持有子VC,并设置子VC的delegate为self(也就是父VC ...

  2. iOS 内存泄漏排查方法及原因分析

    级别: ★★☆☆☆ 标签:「iOS」「内存泄漏排查」「Leaks工具」 作者: MrLiuQ 审校: QiShare团队 本文将从以下两个层面解决iOS内存泄漏问题: 内存泄漏排查方法(工具) 内存泄 ...

  3. MLeaksFinder :腾讯开源的 iOS 内存泄漏检测工具

    一.工具简介 MLeaksFinder :腾讯开源的 iOS 内存泄漏检测工具 工具优势:在日常开发调试或测试业务逻辑过程中,可以自动发现并警告内存泄漏.暂时没有发现误报:基本上报了leak的  进去 ...

  4. Java 中发生内存泄漏 5 个场景以及解决方法

    前言 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和 Java 联系起来.在 Java 中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给了JVM ...

  5. IOS内存泄漏动静态方法排查

    文章目录 简单观察内存 静态分析 概念 可排查到的问题 具体的操作 部分问题及解决 动态分析 概念 具体的操作 数据分析 statistics allocations list generations ...

  6. 什么是内存泄漏,常见引起引起内存泄漏的原因,及解决办法

    一:什么是内存泄露 内存泄露是指:内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元.直到程序结束.(其实说白了就是该内存 ...

  7. c++ thread 内存泄漏_深入剖析ThreadLocal原理、内存泄漏及应用场景

    本文主要针对JDK1.8讲解 ThreadLocal作用 先看一个简单的示例,创建两个线程,第一个线程向ThreadLocal中写入数据,第二个线程等待第一个线程完成从ThreadLocal中读取数据 ...

  8. 内存泄漏的常见应用领域

    1.Java内存泄漏是每个Java程序员都会遇到的问题,程序在本地运行一切正常,可是布署到远端就会出现内存无限制的增长,最后系统瘫痪,那么如何最快最好的检测程序的稳定性,防止系统崩盘,作者用自已的亲身 ...

  9. 内存泄漏以及常见的解决方法

    之所以撰写这篇文章是由于前段时间花费了非常大的精力在已经成熟的代码上再去处理memory leak问题.写此的目的是希望我们应该养成良好的编码习惯,尽可能的避免这种问题,由于当你对着一大片的代码再去处 ...

最新文章

  1. ubuntu 安装linux 下vmVMware tools 步骤及问题解决
  2. 垃圾回收在哪一章java_Java垃圾回收机制
  3. 一秒钟世界上会发生多少事_1秒钟世界上会发生多少事?答案超乎你的想象……...
  4. html语言词典,编程字典-HTML5语法
  5. 在VC++中生成伪随机数祥解
  6. ubuntu安装matlab2009,Ubuntu中安装Matlab2010a
  7. gensim提取一个句子的关键词_聊一聊 NLPer 如何做关键词抽取
  8. mysql无法启动如何备份文件_mysql 5.7 停电导致无法启动、如何备份数据,重新安装mysql...
  9. vscode 不支持的客户端_Windows平台上有哪些你不知道的神器?
  10. uboot移植主要思路
  11. CDR X4无法使用怎么解决
  12. Vue - 引入集成 Tinymce 富文本编辑器(详细步骤及运行Demo),在 Vue.js 项目中使用富文本插件详细教程,附带超级详细的注释说明
  13. UA STAT687 线性模型II 最小二乘理论1 普通最小二乘法
  14. 微信隐藏功能系列:微信状态里如何加音乐?有2个小技巧
  15. wps临时文件不自动删除_windows 里面TEP文件夹里面的临时文件有的不能删除怎么办?...
  16. ++k与k++区别 和双目运算符结合
  17. python 制作正态分布图,画出拒绝域
  18. FOC控制中Clark/iClark和Park/iPark变换及matpoltlib仿真
  19. VxRail升级软件/固件版本
  20. 基于Protobuf的通讯库--Poppy简介

热门文章

  1. vscode ---- 插件
  2. metasploit下载教程linux,在Debian 10/9系统上安装Metasploit Framework的方法
  3. android通知背景色,android – 更改通知RemoteViews背景颜色
  4. tag 和branch的区别
  5. Android开发笔记(一百五十五)利用GL10描绘点、线、面
  6. Java进阶篇设计模式之十三 ---- 观察者模式和空对象模式
  7. 安装hexo,建站并新建博客
  8. RabbitMQ consumer的一些坑
  9. [链表]同时遍历两个链表
  10. 初学Phreeze 3