全局NSTimer导致的内存泄露及解决办法
2018-01-04 00:00
459 查看
NSTimer在iOS10之前只有如下两个常用方法
这两个方法都有一个
销毁NSTimer计时器只能通过
例如:利用以下demo进行测试
我们知道iOS的内存管理是采用引用计数算法来实现的,当一个对象的引用计数为0的时候系统会回收该对象,对象的
至于解决办法,那就是在不需要计时器的时候调用
但是例子中的定时器封装在一个类的类部要在viewcontroller销毁的时候怎么销毁定时器呢?
可以使用例子中的
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo; + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
这两个方法都有一个
target参数,一般我们都把NSTimer对象作为一个属性,这个时候
target通常传递的是NSTimer属性所在的类对象,也就是
Self,由于NSTimer会强引用这个
target对象,所以导致出现一些问题。
销毁NSTimer计时器只能通过
- (void)invalidate方法,一般的需求下,我们期望计时器在视图的声明周期结束后停止计时器,所以我们可能想在视图类的
- (void)dealloc方法中调用
[self.time invalidate]来停止计时器。但是很遗憾,在视图消失的时候程序并不会调用
- (void)dealloc方法,所以计时器也一直在运行,造成了内存泄露。
例如:利用以下demo进行测试
#import <UIKit/UIKit.h> @interface TestView : UIView @end #import "TestView.h" @interface TestView () @property (strong, nonatomic) NSTimer *timer; @end @implementation TestView - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerTick) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; } return self; } - (void)timerTick { NSLog(@"*******"); } - (void)dealloc { if (self.timer) { [self.timer invalidate]; self.timer = nil; } } - (void)willMoveToSuperview:(UIView *)newSuperview { [super willMoveToSuperview:newSuperview]; if (!newSuperview && self.timer) { [self.timer invalidate]; self.timer = nil; } } @end
我们知道iOS的内存管理是采用引用计数算法来实现的,当一个对象的引用计数为0的时候系统会回收该对象,对象的
- (void)dealloc方法要在对象的引用计数值归零之后才会被调用,由于NSTimer计时器一直强引用着视图类对象,所以视图类对象的引用关系里面一直有计时器对象,导致引用计数不能归零,所以
- (void)dealloc不会被调用。
至于解决办法,那就是在不需要计时器的时候调用
- (void)invalidate方法,但是如果我们计时器的开关是交由外部程序员去实现的,那么我们就只能在文档中嘱咐对方在不需要的时候一定要记得停止计时器,这并不保险。
但是例子中的定时器封装在一个类的类部要在viewcontroller销毁的时候怎么销毁定时器呢?
可以使用例子中的
- (void)willMoveToSuperView:(UIView *)newSuperview方法,可以在方法中销毁定时器,我们发现内存泄漏已经解决,dealloc方法可以执行了,此处dealloc方法可不写。
相关文章推荐
- 关于DLL工程中存在全局变量可能导致MFC内存泄露误报的原因分析及解决办法
- 关于DLL工程中存在全局变量可能导致MFC内存泄露误报的原因分析及解决办法
- 关于DLL工程中存在全局变量可能导致MFC内存泄露误报的原因分析及解决办法
- memset导致的内存泄露问题的解决办法
- QT中使用槽函数来关闭窗口,导致内存泄露的问题以及解决办法
- 解决js函数闭包内存泄露问题的办法
- JVM内存分析及导致内存溢出的不健壮代码及解决办法
- MFC环境osgEarth开发程序内存泄露的解决办法
- tableview滑动导致NSTimer和委托回调停止解决办法
- 虚拟机内存调的过大导致无法恢复也无法关闭解决办法
- 解决MyBatis的SqlSession不及时close导致的内存泄露一例
- WINCE-MFC-CDC使用出现的4KB内存泄露解决办法,坑爹的MFC
- TSVNCache狂占内存导致诸多问题的解决办法
- ExtJs发布大量内存泄露的解决办法
- 图片生成操作属性导致WP内存溢出解决办法
- 利用RunTime解决由NSTimer导致的内存泄漏
- 使用Handler导致内存泄露的解决方法
- 内存故障导致死机现象及解决办法
- 转 JVM内存分析及导致内存溢出的不健壮代码及解决办法
- Handler引起的内存泄露及解决办法