Swift – scheduledTimer秒表小时部分不工作

忍受我一个星期前,我拿起了Swift和Xcode(我创build了一个应用程序,在我的假期期间学习Swift)

我使用scheduledTimer创build了一个计时器来充当秒表。 秒和分钟运行良好,但我不能得到的工作时间。 我究竟做错了什么?

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)" } 

正如其他人所说,你不应该试图跟踪自己的时间。 让系统判断已经过了多less时间。 而且,我倾向于使用DateComponentsFormatter为您设置string格式:

 @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() } 

顺便说一句,这是一个微妙的一点,但请注意在Timer闭包的捕获列表中使用[weak self] 。 如果没有这个,那么你有一个很强的参考周期的变化,因为在你invalidate它们invalidate之前,定时器不会停止,但是直到定时器对视图控制器的强引用被parsing,视图控制器的deinit才能被调用。 通过在闭包中使用[weak self]捕获列表,我们打破了这个循环,允许视图控制器在被解散时被释放,并且会停止定时器。

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

  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)" }