Swift: Updating label inside a loop

1525 views swift
5

I have a function that can run for a while. While it is running, I want to provide feedback on the screen.

The problem is that the label.text is not updating.

I suspect this is because I need to execute the function in the background, otherwise execution "halts" in the viewDidAppear method. But if I do that, I think updates in the background do not update the text as well. So I think I must update the label.text on the main thread again.

But I get a runtime error when I do this:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        DispatchQueue.main.async {
            for i in 1...10 {
                DispatchQueue.main.sync {
                    self.label.text = "Working on item \(i)..."
                }
                sleep(1)
            }
        }
    }
}

I had a look at this post, but the methods appear to be dated and do not work in Xcode 10 / Swift 4.

answered question

What runtime error do you get?

I would try losing the first DispatchQueue block and make the inner one .async

2 Answers

4

You may need

class ViewController: UIViewController { 

    var timer:Timer?

    var i = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { (t) in

            self.label.text = "Working on item \(self.i)..."

            self.i+=1

            if self.i == 10 {

              t.invalidte()
            }

        })

    }
}

as it's not a good practice to sleep the thread especially if its the main , also no need for this

DispatchQueue.main.async {

as code by default runs in main thread

posted this
13

You can use Timer as below,

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    var count = 1
    Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
        self.label.text = "Working on item \(count)..."
        count += 1
        if count == 10 {
            timer.invalidate()
        }
    }
}

posted this

Have an answer?

JD

Please login first before posting an answer.