项目中经常会遇到需要定时循环执行某些方法的场景,例如发送短信倒计时需求,此时NSTimer
就派上用场了,关于NSTimer
的用法在此就不做多的解释,这里要讨论的是NSTimer
真的可以准确完成定时触发的功能吗?
一、NSTimer是否是精准的?
首先我们先看一下苹果官方对于NSTimer
的定义:
Timers work in conjunction with run loops. 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.
该段概述提到了NSTimer
是基于run loops
运行的,同时NSTimer
必须添加至run loops
后才能够正常触发。
关于run loops
的运行原理,可以参考该篇文章:《Runloop机制解析及应用》。
另外在官方介绍中,提到了下面相关内容:
A timer is not a real-time mechanism. If a timer’s firing time occurs during a long run loop callout or while the run loop is in a mode that isn't monitoring the timer, the timer doesn't fire until the next time the run loop checks the timer. Therefore, the actual time at which a timer fires can be significantly later. See also Timer Tolerance.
该段介绍提到了如果timer
触发的时间点发生在run loops
长时间调出时间或者run loops
所处的模式不对timer
进行监控,此时timer
就不会在指定时间点触发。
由官方文档可知,NSTimer
在某些情况下并不是准确触发的,下面我们模拟一下这些情况:
首先模拟一下NSTimer
正常触发的情况:
- (void)viewDidLoad {
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
}
- (void)timerAction {
NSLog(@"--->timer action");
}
此时的输出如下:
2019-03-04 15:35:18.307775+0800 TempDemo[73807:20248724] --->timer action
2019-03-04 15:35:19.306643+0800 TempDemo[73807:20248724] --->timer action
2019-03-04 15:35:20.307151+0800 TempDemo[73807:20248724] --->timer action
2019-03-04 15:35:21.307057+0800 TempDemo[73807:20248724] --->timer action
2019-03-04 15:35:22.307683+0800 TempDemo[73807:20248724] --->timer action
2019-03-04 15:35:23.307638+0800 TempDemo[73807:20248724] --->timer action
由输出可知,在正常情况下,NSTimer
可以保证精确触发,触发时机的误差保持在1ms之内。
1. NSTimer触发时间点在run loops长时间调出期间
该情况如何理解呢?
其实run loops
是在循环不断的处理不同类型的事件,其中NSTimer
属于CFRunLoopTimerRef
类型的事件,如图所示:
当run loops
处于正常