NSTimer主要用于开启定时任务,但要真确使用才能保证其正常有效运行。尤其要注意以下两点:
- 确保NSTimer已经添加到当前RunLoop;
- 确保当前RunLoop已经启动。
1.创建NSTimer有两种方法:
+ (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;
这两种方法的主要区别为,使用timerWithTimeInterval创建的timer不会自动添加到当前RunLoop中,需要手动添加并制定RunLoop的模式:[[NSRunLoop currentRunLoop] addTimer:mainThreadTimer forMode:NSDefaultRunLoopMode]; 而使用scheduledTimerWithTimeInterval创建的RunLoop会默认自动添加到当前RunLoop中。
2.NSTimer可能在主线程中创建,也可能在子线程中创建:
主线程中的RunLoop默认是启动的,所以timer只要添加到主线程RunLoop中就会被执行;而子线程中的RunLoop默认是不启动的,所以timer添加到子线程RunLoop中后,还要手动启动RunLoop才能使timer被执行。
NSTimer只有添加到启动起来的RunLoop中才会正常运行。NSTimer通常不建议添加到主线程中执行,因为界面的更新在主线程中,界面导致的卡顿会影响NSTimer的准确性。
以下为四种情形下正确的使用方法:
- (void)viewDidLoad {
[super viewDidLoad];
/* 主线程中创建timer */
NSTimer *mainThreadTimer = [NSTimer timerWithTimeInterval:10.0 target:self selector:@selector(mainThreadTimer_SEL) userInfo:nil repeats:YES];
NSTimer *mainThreadSchduledTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(mainThreadSchduledTimer_SEL) userInfo:nil repeats:YES];
/* 将mainThreadTimer1添加到主线程runloop */
[[NSRunLoop currentRunLoop] addTimer:mainThreadTimer forMode:NSDefaultRunLoopMode];
/* 子线程中创建timer */
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSTimer *subThreadTimer = [NSTimer timerWithTimeInterval:10.0 target:self selector:@selector(subThreadTimer_SEL) userInfo:nil repeats:YES];
NSTimer *subThreadSchduledTimer = [NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:@selector(subThreadSchduledTimer_SEL) userInfo:nil repeats:YES];
/* 将subThreadTimer1添加到子线程runloop */
[[NSRunLoop currentRunLoop] addTimer:subThreadTimer forMode:NSDefaultRunLoopMode];
/* 启动子线程runloop */
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
});
}
- (void) mainThreadTimer_SEL{
NSLog(@"mainThreadTimer is working!");
}
- (void) mainThreadSchduledTimer_SEL{
NSLog(@"mainThreadSchduledTimer is working!");
}
- (void) subThreadTimer_SEL{
NSLog(@"subThreadTimer is working!");
}
- (void) subThreadSchduledTimer_SEL{
NSLog(@"subThreadSchduledTimer is working!");
}
打印结果为:
2018-01-31 20:24:10.729259+0800 IOSDemo[41891:4382661] mainThreadSchduledTimer is working!
2018-01-31 20:24:20.728351+0800 IOSDemo[41891:4382661] mainThreadTimer is working!
2018-01-31 20:24:20.728409+0800 IOSDemo[41891:4382720] subThreadTimer is working!
2018-01-31 20:24:20.728693+0800 IOSDemo[41891:4382720] subThreadSchduledTimer is working!
NSTimer的释放方法:
[timer invalidate];