【问题标题】:Swift - scheduledTimer stopwatch hours portion not workingSwift - scheduleTimer 秒表小时部分不起作用
【发布时间】:2017-06-14 22:19:42
【问题描述】:

请耐心等待我一周前学习了 Swift 和 Xcode(我正在创建一个应用来在假期学习 Swift)

我使用 scheduleTimer 创建了一个计时器来充当秒表。秒和分钟运行良好,但我无法获得工作时间。我做错了什么?

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

【问题讨论】:

  • 如果当前时间经过秒,则小时为currentTime/3600。我不知道你为什么要乘以 20。无论如何,这种方法可能不是最好的。计时器不准确。更好的方法是在秒表启动时创建Date,并在计时器计时时计算该日期与“现在”之间的差异。 DateComponents 可以帮助你从日期获取字段。
  • 是的,20 应该是 3600,但我将它设置为 20,所以我不必等待一个小时来查看它是否有效。我将 hoursPortion 设置为相乘,因为我认为 1 小时 = 3600 秒。
  • 不,你想除法,因为 1 小时 = 3600 秒;如果currentTime = 3600 那么就是1小时,所以currentTime / 3600

标签: ios swift nstimer


【解决方案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] 捕获列表,我们打破了这个循环,允许视图控制器在它被关闭时被释放,它会为你停止计时器。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 感谢您的有用评论!我最终没有将它用于我正在从事的项目,但我测试了一些东西并让它工作。如何格式化计时器以显示 00:02:20 2 分 20 秒?
    • 使用您在最初问题中使用的 String(format:) 方法,或使用 Rob 的 DateComponentsFormatter 建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-03
    • 2021-07-05
    • 2016-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多