作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在用户定义的时间运行一个计时器。如果我将其设置为 1 分钟并启动它,计时器将跳过第 59 秒并在稍有延迟后从 58 秒开始计时。当我离开 View 并返回时,它会重建计时器并删除经过的差异,但又会减少一秒钟,因此它会使计时器非常不准确!
知道为什么会这样吗?下面是我的计时器代码的核心,如果这还不够,我可以提供任何需要的更广泛的代码:
func createTimer(stopDate: Date) {
print("CONSTRUCTING A TIMER")
userDefaults.set(stopDate, forKey: "setStopDate")
restTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(RestController.updateRestTimer), userInfo: nil, repeats: true)
}
func updateRestTimer() {
let presentTime = Date()
let stoppedTime = UserDefaults.standard.object(forKey: "setStopDate") as? Date
if stoppedTime?.compare(presentTime) == .orderedDescending {
restRemainingCountdownLabel.text = dateComponentsFormatter.string(from: presentTime, to: stoppedTime!) // this is where that first second is missed
print(stoppedTime as Any)
} else {
self.stopTimer()
userDefaults.set(nil, forKey: "ViewDidChangeTime")
self.restRemainingCountdownLabel.text = "Done"
}
}
let dateComponentsFormatter: DateComponentsFormatter = {
let _formatter = DateComponentsFormatter()
_formatter.allowedUnits = [.minute, .second]
_formatter.unitsStyle = .positional
_formatter.zeroFormattingBehavior = .pad
return _formatter
}()
最佳答案
首先,您决定停止时间。然后,在一小段时间后,您安排一个计时器在 1 秒内触发(从您的停止时间算起略小于 59 秒)。
在一秒过去后的某个时间点(计时器并不完美,但它们永远不会早),您的计时器将触发,然后您将获取当前时间。此时距离您的停止时间 肯定 不到 59 秒(所有小错误都在一个方向上,向前,所以它们复合)。即使误差平衡,它们也可能不会完美平衡。
好的,距离停止时间大约在 58 到 59 秒之间。好吧,几乎可以肯定超过 58 秒,并且保证少于 59 秒。然后将其交给允许分和秒的日期组件格式化程序。
日期组件格式化程序不舍入。 "大于 58 小于 59"是 58。所以它打印 58。
您可能想要的是舍入,但格式化程序会截断。那没问题;将截断转为舍入很容易:只需在截断前加一半即可。因为你在倒计时,所以你想从当前时间减去 0.5(因为两个负数变成正数;或者你可以计算差值然后加上 0.5,但这更容易):
let presentTime = Date().addingTimeInterval(-0.5)
关于ios - 计时器每次触发时都会跳过第一秒?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42072419/
我是一名优秀的程序员,十分优秀!