ios - NSTimer中target的self是强引用问题
2016-05-05 10:45
393 查看
当控制器ViewController跳转进入控制器OneViewController中的时候开启定时器,让定时器每隔一段时间打印一次,当OneViewController dismiss的时候,控制器并没有被销毁.然而定时器的timer invalidate 在dealloc中已经写了.
如果没有定时器,则OneViewController可以正常销毁.
原因在于下图:循环引用
![](https://images2015.cnblogs.com/blog/831196/201605/831196-20160505103205451-1299453023.png)
控制器ViewController跳转进入OneViewController中开启定时器
当开启定时器以后,testTimerDeallo方法一直执行,即使dismiss此控制器以后,也是一直在打印,而且dealloc方法不会执行.循环引用造成了内存泄露,控制器不会被释放.
解决办法: 由于循环引用的起因是target,则可以包装一个target,让target是另一个对象,而不是ViewController即可.
1.创建一个集成NSObject的分类TimerWeakTarget,创建类方法---开启定时器的方法
TimerWeakTarget.m文件中
在下面我们封装的类的方法中,我们将开启定时器的方法 [NSTimer scheduledTimerWithTimeInterval:interval target:timer selector:@selector(fire:) userInfo:userInfo repeats:repeats];中的target换掉了,换成了 本类的对象,timer.在OneViewController中开启定时器的时候直接调用这个类方法,就不会造成循环引用.看图
![](https://images2015.cnblogs.com/blog/831196/201605/831196-20160505104315294-1803646750.png)
控制器dismiss以后可以正常被销毁.问题解决.
如果没有定时器,则OneViewController可以正常销毁.
原因在于下图:循环引用
![](https://images2015.cnblogs.com/blog/831196/201605/831196-20160505103205451-1299453023.png)
控制器ViewController跳转进入OneViewController中开启定时器
#import "OneViewController.h" @interface OneViewController () @property (nonatomic, strong) NSTimer *timer; @end @implementation OneViewController -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ [self dismissViewControllerAnimated:YES completion:nil]; } -(void)viewDidLoad{ [super viewDidLoad]; self.view.backgroundColor = [UIColor orangeColor]; /** 1.__weak typeof(self) weakSelf = self; 不能解决 */ //开启定时器 self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(testTimerDeallo) userInfo:nil repeats:YES]; } /** 方法一直执行 */ -(void)testTimerDeallo{ NSLog(@"-----"); }
当开启定时器以后,testTimerDeallo方法一直执行,即使dismiss此控制器以后,也是一直在打印,而且dealloc方法不会执行.循环引用造成了内存泄露,控制器不会被释放.
/** 开启定时器以后控制器不能被销毁,此方法不会被调用 */ -(void)dealloc{ NSLog(@"xiaohui"); [self.timer invalidate]; } @end
解决办法: 由于循环引用的起因是target,则可以包装一个target,让target是另一个对象,而不是ViewController即可.
1.创建一个集成NSObject的分类TimerWeakTarget,创建类方法---开启定时器的方法
#import <Foundation/Foundation.h> @interface TimerWeakTarget : NSObject @property (nonatomic, assign) SEL selector; @property (nonatomic, weak) NSTimer *timer; @property (nonatomic, weak) id target; /** 1.重写开启定时器方法,在内部对target进行替换,换成本类(TimerWeakTarget)的对象即可 2.不会造成循环引用了,原控制器OneViewController属性有timer对timer强应用,timer内部对self强引用,但是self在此方法内部被替换成了本类的对象(TimerWeakTarget *),而本类的对象不会对OneViewController强引用,则不会造成循环引用,也就不会造成内存泄露 */ + (NSTimer *) scheduledTimerWithTimeInterval:(NSTimeInterval)interval target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats; @end
TimerWeakTarget.m文件中
在下面我们封装的类的方法中,我们将开启定时器的方法 [NSTimer scheduledTimerWithTimeInterval:interval target:timer selector:@selector(fire:) userInfo:userInfo repeats:repeats];中的target换掉了,换成了 本类的对象,timer.在OneViewController中开启定时器的时候直接调用这个类方法,就不会造成循环引用.看图
![](https://images2015.cnblogs.com/blog/831196/201605/831196-20160505104315294-1803646750.png)
#import "TimerWeakTarget.h" @implementation TimerWeakTarget + (NSTimer *) scheduledTimerWithTimeInterval:(NSTimeInterval)interval target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats{ TimerWeakTarget * timer = [TimerWeakTarget new]; timer.target = aTarget; timer.selector = aSelector; //-------------------------------------------------------------此处的target已经被换掉了不是原来的VIewController而是TimerWeakTarget类的对象timer timer.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:timer selector:@selector(fire:) userInfo:userInfo repeats:repeats]; return timer.timer; } -(void)fire:(NSTimer *)timer{ if (self.target) { [self.target performSelector:self.selector withObject:timer.userInfo]; } else { [self.timer invalidate]; } } @end
控制器dismiss以后可以正常被销毁.问题解决.
相关文章推荐
- ios开发--网页中调用JS与JS注入
- iOS 弹出选项卡,并附带遮罩
- 解决ios真机调试team ID not found问题
- iOS 设置圆角
- iOS中如何判断中英文混合的字符长度
- iOS开发遍历集合(NSArray,NSDictionary、NSSet)方法总结
- iOS百度地图-BMK标注&amp;覆盖物
- ios开发笔记-设置带图片的button的圆角在AL下失效
- 无比迅速敏捷地开发iOS超精美控件
- ios开发技巧
- iOS应用发布中的一些细节
- iOS开发——Xcode快捷键
- ios ViewController生命周期 ---- push跳转和模态跳转的VC生命周期
- 《Motion Design for iOS》(十一)
- iOS之AFNetworking基本使用
- iOS viewcontroller生命周期
- iOS之修改项目BUG之旅--(一)
- IOS NSPredicate 查询、搜索(详解)
- iOS之提示框的道道
- 【代码笔记】iOS-判断中英文混合的字符长度的两种方法