经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » iOS » 查看文章
【Swift】Timer定时器到底准不准确?
来源:cnblogs  作者:Landen丶  时间:2020/11/9 15:59:48  对本文有异议

  在开发过程中,Timer可以说是比较常见的了,用来做一些定时性的操作。可实际过成功,Timer的时间真的准吗?下面写几个代码来做验证。

  1、Timer

  1. timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(timerTest), userInfo: nil, repeats: true)
  2. @objc func timerTest() {
  3. print("timer info - \(Date.init())")
  4. }

  运行结果:

  1. timer info - 2020-10-28 05:02:33 +0000
  2. timer info - 2020-10-28 05:02:34 +0000
  3. timer info - 2020-10-28 05:02:35 +0000
  4. timer info - 2020-10-28 05:02:36 +0000

  看结果还是比较准备的,不妨加大量继续测试。在输入时加一些耗时操作。

  1. @objc func timerTest() {
  2. var count = 0
  3. for index in 0..<100000 {
  4. count += 1
  5. }
  6. print("timer info - \(Date.init())")
  7. }

  再看运行结果:

  1. timer info - 2020-10-28 05:04:20 +0000
  2. timer info - 2020-10-28 05:04:21 +0000
  3. timer info - 2020-10-28 05:04:22 +0000
  4. timer info - 2020-10-28 05:04:23 +0000
  5. timer info - 2020-10-28 05:04:24 +0000
  6. timer info - 2020-10-28 05:04:25 +0000
  7. timer info - 2020-10-28 05:04:26 +0000

  还可以嘛!结果依然看起来挺对的,那就继续加大工作量。再测试:

  1. @objc func timerTest() {
  2. var count = 0
  3. for index in 0..<10000000 {
  4. count += 1
  5. }
  6. print("timer info - \(Date.init())")
  7. }

  看运行结果:

  1. timer info - 2020-10-28 05:05:19 +0000
  2. timer info - 2020-10-28 05:05:23 +0000
  3. timer info - 2020-10-28 05:05:27 +0000
  4. timer info - 2020-10-28 05:05:31 +0000

  这时候结果就明显了,我要求的定时是1秒钟,可间隔出现了竟然4秒了。这跟我要求的就相差很大了。可这是怎么出现的呢?

  原因分析:

  定时器被添加在主线程中,由于定时器在一个RunLoop中被检测一次,所以如果在这一次的RunLoop中做了耗时的操作,当前RunLoop持续的时间超过了定时器的间隔时间,那么下一次定时就被延后了。

  解决办法:

  1、在子线程中创建timer,在主线程进行定时任务的操作
  2、在子线程中创建timer,在子线程中进行定时任务的操作,需要UI操作时切换回主线程进行操作  

  1. Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer) in
  2. print("timer info - \(Date.init())")
  3. }

  2、RunLoop模式的影响

  为了验证,我们在当前页面上添加一个tableview,在定时器运行时,我们对tableview进行滑动操作,可以发现,定时器并不会触发下一次的定时任务。

  原因分析:

  主线程的RunLoop有两种预设的模式,RunLoopDefaultMode和TrackingRunLoopMode。
  当定时器被添加到主线程中且无指定模式时,会被默认添加到DefaultMode中,一般情况下定时器会正常触发定时任务。但是当用户进行UI交互操作时(比如滑动tableview),主线程会切换到TrackingRunLoopMode,在此模式下定时器并不会被触发。

  解决方法:

  添加定时器到主线程的CommonMode中或者子线程中

  1. timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(timerTest), userInfo: nil, repeats: true)
  2. //
  3. RunLoop.main.add(timer, forMode: .common)

  总结

  从结果看,Timer在其使用场景下足够准了,对于“不准”更多是集中在对其错误的使用方式上,只要我们足够深入了解,正确地使用,就能让它“准”。

  实际上,苹果也不推荐使用太高精度的定时器,对于Timer,精度在50-100ms都是正常的,如果我们需要足够高精度地进行计时,比如统计APP启动时间、一段任务代码的运行时间等等,Timer不是一个好的选择,mach_absolute_time()或者可以帮到你,苹果开发工具也带有更专业的API或者插件提供给开发者。

 

原文链接:http://www.cnblogs.com/xjf125/p/13890489.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号