【问题标题】:Updating UILabel when timer counts down each second in Swift 4.2在 Swift 4.2 中当计时器每秒倒计时时更新 UILabel
【发布时间】:2018-10-26 11:58:28
【问题描述】:

新人在这里自学 Swift。构建我的第一个个人应用程序,并在此处、youtube 和 google 上进行了多次搜索后碰壁了。这是我第一次发布问题(因为我已经能够在这里找到我的其他答案)。

我在UILabel 上更新计时器时遇到问题。我设法在旧版本的 swift 上找到了让计时器运行和倒计时的代码。然后我想出了如何将秒分解为分钟和秒。

但我发现当我运行应用程序时,计时器显示 "30:0"(我需要解决一个不同的问题)并且从不倒计时。当我将页面留在模拟器中并返回时,UILabel 才会更新。

我知道 viewdidload 仅在页面打开的第一刻加载。我很难弄清楚如何让 UILabel 在每秒钟发生变化时更新。我不确定要实现什么代码。

非常感谢!

import UIKit

var timer = Timer()
var timerDuration: Int = 1800

// This converts my timeDuration from seconds to minutes and seconds.
func secondsToHoursMinutesSeconds (seconds : Int) -> (h: Int, m : Int, s : Int) {
    return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)
}

class lyricWriteViewController: UIViewController {
    //This takes the function to convert minutes and seconds and accepts an input, which I've chosen the variable timeDuration (which is currently 1800 seconds.
    var theTimer = (h: 0, m: 0, s: 0)

    @IBOutlet weak var countdownTimer: UILabel!
    @IBOutlet weak var randomLyric: UILabel!
    @IBOutlet weak var titleInput: UITextField!
    @IBOutlet weak var lyricInput: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        //This line takes a random array number and shows it on the textlabel.

        randomLyric.text = oneLiner
        theTimer = secondsToHoursMinutesSeconds(seconds: timerDuration)

        //This is the code the does the counting down
        timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(lyricWriteViewController.counter), userInfo: nil, repeats: true)
    }

    @objc func counter() {
        timerDuration -= 1

        // Below is the timer view I've created. It has converted seconds to minutes and seconds but the screen won't refresh. Also, when the seconds number hits zero, it does "0" instead of "00".
        let displayTimer = "\(theTimer.m) : \(theTimer.s)"
        countdownTimer.text = String(displayTimer)

        //When the timer hits 0, it stops working so that it doesn't go into negative numbers

        if timerDuration == 0 {
            timer.invalidate()
        }
    }

    func submitlyricsButton(_ sender: UIButton) {
        //I will eventually tie this to a completed lyric tableview.
    }
}

【问题讨论】:

  • 为了确保你的计时器工作正常,你能不能在你做countdownTimer.text = String(displayTimer)之前写一个日志并打印displayTimer的值
  • 计时器工作,但我遇到的唯一问题是它在 0-9 之前显示“0”。例如:29:10、29:9、29:8。而不是 29:09、29:08... 等。

标签: ios swift timer countdown swift4.2


【解决方案1】:
var timer: Timer?
var totalTime = 120

private func startOtpTimer() {
    self.totalTime = 120
    self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)
}

@objc func updateTimer() {
    print(self.totalTime)
    self.lblTimer.text = self.timeFormatted(self.totalTime) // will show timer
    
    if totalTime != 0 {
        totalTime -= 1 // decrease counter timer
    } 
    else {
        if let timer = self.timer { 
            timer.invalidate()
            self.timer = nil
        }
    }
}

func timeFormatted(_ totalSeconds: Int) -> String {
    let seconds: Int = totalSeconds % 60
    let minutes: Int = (totalSeconds / 60) % 60
    return String(format: "%02d:%02d", minutes, seconds)
}

【讨论】:

    【解决方案2】:

    这是因为您没有更新 theTimer 值。因为viewDidLoad()一旦不能正常工作就会被调用,你需要在减去1之后更新theTimer的值。 所以移动这一行:

    theTimer = secondsToHoursMinutesSeconds(seconds: timerDuration)
    

    counter() 函数中timerDuration -= 1 之后。所以你的函数应该是这样的:

    @objc func counter() {
        timerDuration -= 1
        if timerDuration == 0 {
            timer.invalidate()
        } else {
            theTimer = secondsToHoursMinutesSeconds(seconds: timerDuration)
            let displayTimer = "\(theTimer.m) : \(theTimer.s)"
            countdownTimer.text = String(displayTimer)
        }        
    }
    

    也将所有这些都移动到控制器内部:

    var timer = Timer()
    var timerDuration: Int = 1800
    
    // This converts my timeDuration from seconds to minutes and seconds.
    func secondsToHoursMinutesSeconds (seconds : Int) -> (h: Int, m : Int, s : Int){
    return (seconds / 3600, (seconds % 3600) / 60, (seconds % 3600) % 60)}
    

    由于 timerDuration 是全局的,您必须终止应用并再次运行它才能看到计时器再次工作。

    【讨论】:

    • 太棒了!非常感谢你。这对我来说是一个很好的学习。这是一个简单的调整,但如果没有你,我不会想出来的。谢谢!
    【解决方案3】:

    countdownTimer.text = String(displayTimer) 替换为

    DispatchQueue.main.async {
        countdownTimer.text = String(displayTimer)
    }
    

    我认为这里发生的事情是因为countdownTimer.text = String(displayTimer) 没有在主线程上运行,它不会立即更新。然而,它会在一段时间后(就像你说的那样,当你遍历屏幕时)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多