Обновление UILabel, когда таймер отсчитывает каждую секунду в Swift 4.2 - PullRequest
0 голосов
/ 26 октября 2018

Новый парень учил себя Свифту.Создаю свое первое личное приложение и врезался в стену после нескольких поисков здесь, на 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 голосов
/ 26 октября 2018
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)
}
0 голосов
/ 26 октября 2018

Это потому, что вы не обновляете значение theTimer. Поскольку viewDidLoad() вызывается, когда он не работает нормально, вам необходимо обновить значение theTimer после вычета 1 из него. Итак, переместите эту строку:

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 является глобальным, вам придется закрыть приложение и запустить его снова, чтобы увидеть, как таймер снова работает.

0 голосов
/ 26 октября 2018

Заменить countdownTimer.text = String(displayTimer) на

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

Я думаю, что здесь происходит, так как countdownTimer.text = String(displayTimer) не работает в главном потоке, он не обновляется немедленно. Это происходит после определенного периода времени (как вы сказали, когда вы пересекаете экран).

...