在开发过程当中,Timer能够说是比较常见的了,用来作一些定时性的操做。可实际过成功,Timer的时间真的准吗?下面写几个代码来作验证。工具
timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(timerTest), userInfo: nil, repeats: true) @objc func timerTest() { print("timer info - \(Date.init())") }
运行结果:oop
timer info - 2020-10-28 05:02:33 +0000 timer info - 2020-10-28 05:02:34 +0000 timer info - 2020-10-28 05:02:35 +0000 timer info - 2020-10-28 05:02:36 +0000
看结果仍是比较准备的,不妨加大量继续测试。在输入时加一些耗时操做。开发工具
@objc func timerTest() { var count = 0 for index in 0..<100000 { count += 1 } print("timer info - \(Date.init())") }
再看运行结果:测试
timer info - 2020-10-28 05:04:20 +0000 timer info - 2020-10-28 05:04:21 +0000 timer info - 2020-10-28 05:04:22 +0000 timer info - 2020-10-28 05:04:23 +0000 timer info - 2020-10-28 05:04:24 +0000 timer info - 2020-10-28 05:04:25 +0000 timer info - 2020-10-28 05:04:26 +0000
还能够嘛!结果依然看起来挺对的,那就继续加大工做量。再测试:spa
@objc func timerTest() { var count = 0 for index in 0..<10000000 { count += 1 } print("timer info - \(Date.init())") }
看运行结果:插件
timer info - 2020-10-28 05:05:19 +0000 timer info - 2020-10-28 05:05:23 +0000 timer info - 2020-10-28 05:05:27 +0000 timer info - 2020-10-28 05:05:31 +0000
这时候结果就明显了,我要求的定时是1秒钟,可间隔出现了居然4秒了。这跟我要求的就相差很大了。可这是怎么出现的呢?线程
定时器被添加在主线程中,因为定时器在一个RunLoop中被检测一次,因此若是在这一次的RunLoop中作了耗时的操做,当前RunLoop持续的时间超过了定时器的间隔时间,那么下一次定时就被延后了。code
一、在子线程中建立timer,在主线程进行定时任务的操做
二、在子线程中建立timer,在子线程中进行定时任务的操做,须要UI操做时切换回主线程进行操做 blog
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in print("timer info - \(Date.init())") }
为了验证,咱们在当前页面上添加一个tableview,在定时器运行时,咱们对tableview进行滑动操做,能够发现,定时器并不会触发下一次的定时任务。开发
主线程的RunLoop有两种预设的模式,RunLoopDefaultMode和TrackingRunLoopMode。
当定时器被添加到主线程中且无指定模式时,会被默认添加到DefaultMode中,通常状况下定时器会正常触发定时任务。可是当用户进行UI交互操做时(好比滑动tableview),主线程会切换到TrackingRunLoopMode,在此模式下定时器并不会被触发。
添加定时器到主线程的CommonMode中或者子线程中
timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(timerTest), userInfo: nil, repeats: true) // RunLoop.main.add(timer, forMode: .common)
从结果看,Timer在其使用场景下足够准了,对于“不许”更可能是集中在对其错误的使用方式上,只要咱们足够深刻了解,正确地使用,就能让它“准”。
实际上,苹果也不推荐使用过高精度的定时器,对于Timer,精度在50-100ms都是正常的,若是咱们须要足够高精度地进行计时,好比统计APP启动时间、一段任务代码的运行时间等等,Timer不是一个好的选择,mach_absolute_time()或者能够帮到你,苹果开发工具也带有更专业的API或者插件提供给开发者。