Swift - scheduledTimer秒表小时部分无效

时间:2017-06-14 22:19:42

标签: ios swift nstimer

忍受我一周前我选择了Swift和Xcode(我在假期期间创建了一个学习Swift的应用程序)

我使用scheduledTimer创建了一个计时器作为秒表。秒和分钟运行正常,但我无法让时间工作。我做错了什么?

currentTime = 0
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in

    self.currentTime += 1

    let hoursPortion = String(format: "%02d", CGFloat(self.currentTime) * 60)
    let minutesPortion = String(format: "%02d", self.currentTime / 60)
    let secondsPortion = String(format: "%02d", self.currentTime % 60)
    //let tenPortion = String(format: "%d", self.currentTime * 10 % 10)
    self.TimerDisplay.text = "\(hoursPortion):\(minutesPortion):\(secondsPortion)"
}

2 个答案:

答案 0 :(得分:1)

正如其他人所说,你不应该试图自己跟踪时间。让系统计算出已经过了多长时间。并且,我倾向于使用DateComponentsFormatter为您格式化字符串:

@IBOutlet weak var elapsedLabel: UILabel!

weak var timer: Timer?

private var formatter: DateComponentsFormatter = {
    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .positional
    formatter.allowedUnits = [.hour, .minute, .second]
    formatter.zeroFormattingBehavior = .pad
    return formatter
}()

private func startTimer() {
    timer?.invalidate()      // stop prior timer, if any

    let startTime = Date()

    timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
        self?.elapsedLabel.text = self?.formatter.string(from: startTime, to: Date())
    }
}

deinit {
    timer?.invalidate()
}
顺便说一句,这是一个微妙的观点,但请注意在[weak self]闭包的捕获列表中使用Timer。如果没有这个,你有一个强大的参考周期的变化,因为定时器不会停止,直到你invalidate,但视图控制器的deinit无法被调用,直到定时器的强引用视图控制器已解决。通过在闭包中使用[weak self]捕获列表,我们打破了该循环,允许视图控制器在被解除时被释放,并且它将为您停止计时器。

答案 1 :(得分:0)

这不是最好的方法,因为定时器不能保证足够准确,它会随着时间的推移而漂移。更好的方法是记录开始时间并使用日历功能为您提供已用时间。例如

        let startTime = Date()
        let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
            let now = Date()
            let components = Calendar.current.dateComponents([.hour, .minute, .second], from: startTime, to: now)

            guard let hoursPortion = components.hour, let minutesPortion = components.minute, let secondsPortion = components.second
            else {
                preconditionFailure("Should not happen")
            }

            self.TimerDisplay.text = "\(hoursPortion):\(minutesPortion):\(secondsPortion)"
        }