我在用户定义的时间运行一个计时器。如果我将其设置为1分钟并将其激活,则计时器将跳过第59秒并在经过一段延迟后从58开始。当我离开视图并返回时,重建计时器并删除经过的时间差,但再次关闭此时间,这样可以使计时器非常不准确!
知道为什么会这样吗?下面是我的定时器代码的核心,如果这还不够,我可以提供任何更广泛的代码:
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
}()
答案 0 :(得分:2)
首先,您决定停止时间。然后,在很短的时间之后,你计划一个计时器在1秒钟内开火(这比你的停止时间稍微少于59秒)。
在一秒钟之后稍微过了一些时间(计时器不完美,但它们从未提前),你的计时器会启动,稍后你会获取当前时间。此时,肯定小于59秒直到停止时间(所有小错误都在一个方向,向前,所以它们复合)。即使错误平衡,它们也可能无法完美平衡。
好的,所以它在58到59秒之间,直到你的停止时间。好吧,几乎可以肯定超过58秒,保证不到59秒。然后将其交给日期组件格式化程序,并允许分钟和秒数。
日期组件格式化程序不会舍入。 “58以上且不到59”是58.所以打印58。
你可能想要的是舍入,但格式化程序会截断。那没问题;很容易将截断变为舍入:在截断之前加上一半。因为你倒计时,你想从当前时间减去0.5(因为两个底片为正;或者你可以计算差值然后加0.5,但这更容易):
let presentTime = Date().addingTimeInterval(-0.5)