Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Threading: When to use DispatchQueue.main.async?

I believe I understand what the dispatch queue is doing when I call it, but I'm not sure when exactly I should use it and what it's advantages are when I do use it.

If my understanding is correct, DispatchQueue.main.async { // code } will schedule the code contained within the closure to run on the main dispatch queue in an asynchronous manner. The main queue has the highest priority, and is typically reserved for updating UI to maximize App responsiveness.

Where I'm confused is: What exactly is the difference in updating UI elements within a dispatch queue closure versus just writing the code outside the closure in the same spot? Is it faster to execute the code in the body of a view did load method rather than sending it to the dispatch queue? If not, why?

Code Example:

class MyViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
    }

}

Versus:

class MyViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        DispatchQueue.main.async {
            updateUI()
        }
    }
}

Which one is will update the UI faster?

like image 947
ICW Avatar asked Jun 06 '18 18:06

ICW


1 Answers

The primary use of DispatchQueue.main.async is when you have code running on a background queue and you need a specific block of code to be executed on the main queue.

In your code, viewDidLoad is already running on the main queue so there is little reason to use DispatchQueue.main.async.

But isn't necessarily wrong to use it. But it does change the order of execution.

Example without:

class MyViewController: UIViewController {
    func updateUI() {
        print("update")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        print("before")
        updateUI()
        print("after")
    }
}

As one might expect, the output will be:

before
update
after

Now add DispatchQueue.main.async:

class MyViewController: UIViewController {
    func updateUI() {
        print("update")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        print("before")
        DispatchQueue.main.async {
            updateUI()
        }
        print("after")
    }
}

And the output changes:

before
after
update

This is because the async closure is queued up to run after the current runloop completes.

like image 132
rmaddy Avatar answered Sep 28 '22 08:09

rmaddy