【问题标题】:How to keep two timers in sync如何保持两个定时器同步
【发布时间】:2020-06-04 00:30:28
【问题描述】:

我对编码和 Swift 还是很陌生。所以请耐心等待。

问题说明:我有一个秒表风格的应用程序,它有两个并发计时器同时启动并以mm:ss.SS 格式显示,但一个设计为重置为0以特定的时间间隔自动进行,而另一个则继续并跟踪总时间。

类似于“圈”功能,但它会自动执行。我遇到的问题是,当用户暂停计时器时,有时计时器不会完全同步。由于重置发生在精确的秒数,因此两个计时器应该具有相同的百分之一秒,而秒数和分钟数显然会有所不同。但有时百分之一会相差 0.01 或更多。

现在,我知道 Timer 的设计并不是完全准确的,实际上在我的应用中,这甚至不是什么大问题。我的计时器甚至不需要精确到百分之一秒,并且在运行时它根本不会明显关闭,只有在暂停时。我可以显示更少的小数位或根本不显示,但我更喜欢显示百分之一的样式,因为它非常适合股票计时器应用程序样式。

所以如果有办法让这个工作,我想保留它。

截图: screenshot

我尝试了什么:

@IBAction func playPauseTapped(_ sender: Any) {
        if timerState == .new {
            //start new timer
            startCurrentTimer()
            startTotalTimer()
            currentStartTime = Date.timeIntervalSinceReferenceDate
            totalStartTime = Date.timeIntervalSinceReferenceDate
            timerState = .running

            //some ui updates
        } else if timerState == .running {
            //pause timer
            totalTimer.invalidate()
            currentTimer.invalidate()
            timerState = .paused
            pausedTime = Date()
            //other ui updates
        } else if timerState == .paused {
            //resume paused timer
            let pausedInterval = Date().timeIntervalSince(pausedTime!)
            pausedIntervals.append(pausedInterval)
            pausedIntervalsCurrent.append(pausedInterval)
            pausedTime = nil
            startCurrentTimer()
            startTotalTimer()
            timerState = .running
            //other ui updates
        }

    }

    func startTotalTimer() {
        totalTimer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(runTotalTimer), userInfo: nil, repeats: true)
    }

    func startCurrentTimer() {
        currentTimer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(runCurrentTimer), userInfo: nil, repeats: true)
    }

    func resetCurrentTimer() {
        currentTimer.invalidate()
        currentStartTime = Date.timeIntervalSinceReferenceDate
        pausedIntervalsCurrent.removeAll()
        startCurrentTimer()
    }

    @objc func runCurrentTimer() {
        let currentTime = Date.timeIntervalSinceReferenceDate

        //calculate total paused time
        var pausedSeconds = pausedIntervalsCurrent.reduce(0) { $0 + $1 }
        if let pausedTime = pausedTime {
            pausedSeconds += Date().timeIntervalSince(pausedTime)
        }

        let currentElapsedTime: TimeInterval = currentTime - currentStartTime - pausedSeconds

        currentStepTimeLabel.text = format(time: currentElapsedTime)

        if currentElapsedTime >= recipeInterval {
            if recipeIndex < recipeTime.count - 1 {
                recipeIndex += 1

                //ui updates

                //reset timer to 0
                resetCurrentTimer()
            } else {
                //last step
                currentTimer.invalidate()
            }

        }
    }

    @objc func runTotalTimer() {
        let currentTime = Date.timeIntervalSinceReferenceDate

        //calculate total paused time
        var pausedSeconds = pausedIntervals.reduce(0) { $0 + $1 }
        if let pausedTime = pausedTime {
            pausedSeconds += Date().timeIntervalSince(pausedTime)
        }

        let totalElapsedTime: TimeInterval = currentTime - totalStartTime - pausedSeconds

        totalTimeLabel.text = format(time: totalElapsedTime)

        if totalElapsedTime >= recipeTotalTime {
            totalTimer.invalidate()
            currentTimer.invalidate()
            //ui updates
        }
    }

    func format(time: TimeInterval) -> String {
        //formats TimeInterval into mm:ss.SS

        let formater = DateFormatter()
        formater.dateFormat = "mm:ss.SS"

        let date = Date(timeIntervalSinceReferenceDate: time)
        return formater.string(from: date)
    }

【问题讨论】:

  • edit你的问题显示相关代码

标签: ios swift timer


【解决方案1】:

您应该使用单个计时器。当您需要重置为零时,请将当前时间保存到变量中。

在 UI 中显示时间时,计算正在运行的总计时器与您之前保存的时间之间的差。

【讨论】:

  • 我最初尝试过这个,但当我的代码变得混乱时放弃了它。我也没有想过在重置为零并使用它时保存当前时间。我最终转向了一个计时器,但也使步进计时器倒计时而不是倒计时。为特定目的提供更好的用户体验,我设法让这一切正常工作。谢谢。
猜你喜欢
  • 1970-01-01
  • 2019-08-11
  • 2011-12-01
  • 2019-07-31
  • 1970-01-01
  • 2018-09-03
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多