在Swift 4.2中每秒钟倒计时时更新UILabel

时间:2018-10-26 11:58:28

标签: ios swift timer countdown swift4.2

这里有新人自学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.
    }
}

3 个答案:

答案 0 :(得分:1)

这是因为您没有更新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是全局的,因此您必须终止该应用程序,然后再次运行它才能看到计时器再次工作。

答案 1 :(得分:0)

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 :(得分:-1)

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

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