相信iOS开发过程中,肯定大多数人都知道Timer的释放不掉问题,但是否认真考虑过其中释放不掉的原因?
self.timer =[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerRun:)userInfo:nil repeats:YES];
不释放原因
Timer添加到Runloop的时候,会被Runloop强引用:
Note in particular that run loops maintain strong references to their timers,so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.
Timer又会有一个对Target的强引用(也就是self):
Target is the object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to target until it(the timer)is invalidated.
You must send this message from the thread on which the timer was installed. If you send this message from another thread,the input source associated with the timer may not be removed from its run loop,which could prevent the thread from exiting properly.
NSTimer 在哪个线程创建就要在哪个线程停止,否则会导致资源不能被正确的释放。
那么问题来了:如果我就是想让这个 NSTimer 一直输出,直到VC 销毁了才停止,我该如何让它停止呢?
方法一:
-(void)willMoveToParentViewController:(nullable UIViewController *)parent {
if(parent == nil){
[_timer invalidate];
_timer = nil;
}
}
方法二:
__weak LeaksViewController * weakSelf = self;
[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer){
[weakSelf fire];
}];
-(void)fire {
NSLog(@"运行");
}
方法三:
NSObject * object =[[NSObject alloc]init];
class_addMethod([NSObject class],@selector(fire),(IMP)fire,"v@:");
_timer =[NSTimer scheduledTimerWithTimeInterval:1.0 target:object selector:@selector(fire)userInfo:nil repeats:YES];
void fire(id self,SEL _cmd){
NSLog(@"运行");
}
-(void)dealloc {
[_timer invalidate];
_timer = nil;
}
方法四:
TimeProxy * proxy =[TimeProxy alloc];
proxy.object = self;
_timer =[NSTimer scheduledTimerWithTimeInterval:1.0 target:proxy selector:@selector(fire)userInfo:nil repeats:YES];
-(void)dealloc {
[_timer invalidate];
_timer = nil;
}