ios - 为什么计时器有时会如此快地调用它的 block

标签 ios nstimer

我创建了一个计时器并每 5 秒调用它的 block 。然后我申请进入后台并在一段时间后进入前台。但有时它可以快速调用该 block 。

let _ = Timer.scheduledTimer(withTimeInterval: 5.0, repeats: true) { (timer) in
        print("--------")
   }

当我进入前台时,第一次打印和第二次打印的间隔有时可能小于一秒。在这种情况下时间间隔无效吗?

最佳答案

要了解该行为,您需要了解 NSTimerRunLoop 的工作原理。简单来说,RunLoop 将检查计时器是否应该触发,如果是,它会通知计时器触发选择器,否则不会。现在,由于您位于后台,您的 RunLoop 不会检查事件,因此无法通知计时器。但是一旦它进入前台,它就会发现即使它超过了 fireDate,它也需要通知 Timer。

时间线图:

设 A(第 5 秒)和 B(第 10 秒)为计时器触发事件​​。在计时器上安排 Timer.scheduledTimer(withTimeInterval: 5.0, Repeats: true)

C进入后台(0秒)

D 回到前台(第 9 秒,在 A 和 B 之间)。

-----> A ------> B

C--------->D

说明:

在 C 上,RunLoop 将暂停。因此,在 RunLoop 恢复处理事件 D 之前,事件 A 无法被处理。在事件 D 上,它将发现事件 A 应该触发,因此它会通知计时器。一秒钟后,RunLoop 会发现事件 B 已经发生,因此它会再次通知 Timer。此场景解释了为什么您的事件以一秒的间隔打印。只是延迟的事件处理使它看起来更早触发,而实际上它被延迟处理。

苹果文档:

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.

资源:What is an NSTimer's behavior when the app is backgrounded? 、NSRunLoop 和计时器文档

建议:

应用进入后台后停止计时器,但存储 fireDate。返回前台后,检查 fireDate 是否超过 Date()。然后创建一个新的计时器来在前台处理事件。

关于ios - 为什么计时器有时会如此快地调用它的 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53624323/

相关文章:

ios - 使用 iOS Openfire 和 Robbie Hanson 库以所有者权限加入现有的 XMPP MUC 房间

javascript - 在使用 iOS Phonegap 包装的 jQuery Mobile 中找不到具有相对 src 的图像

php - iPhone OS 图像/照片大小调整工具可更改 EXIF 方向数据

ios - Cocoa iOS 在 UIView 中制作 CGPoints "Bigger"

iphone - 使用 NSTimer 更新标签以在 10 秒内显示 10000 到 0

ios - 应用内购买不适用于 ios7/从不兼容的类型分配给..

ios - IOS 编程中模型和 View 之间的数据通信

ios5 - 在主线程和后台线程中调度 NSTimer 的区别?

swift - 如何等到计时器停止

ios - 如何使用选择器和时间间隔创建 NSDate 计时器