Search code examples
iosswiftalamofiregrand-central-dispatch

Do I need DispatchQueue.main to update UI after an Alamofire request?


I'm following a tutorial about working with REST/web requests. In the tutorial, we're working towards a Pokedex app where we fetch Pokemon details from an API using Alamofire, and then displaying that data in our UIs.

Here's the related code:

typealias DownloadComplete = (Bool) -> ()

// Model class
func downloadPokemonDetails(completed: @escaping DownloadComplete)
    {
        Alamofire.request(_pokemonURL).responseJSON { (response) in
            var success = true
            if let jsonData = response.result.value as? Dictionary<String, Any>
            {
                // parse the json here
                ...
            }
            else
            {
                success = false
            }
            completed(success)
        }
    }

// Controller class
override func viewDidLoad() {
        super.viewDidLoad()
        pokemon.downloadPokemonDetails(completed: { (success) in
            if success
            {
                self.updateUI()
            }
            else
            {
                print("FAILED: TO PARSE JSON DATA")
            }
        })
    }

func updateUI()
{
    attackLbl.text = pokemon.attack
    defenseLbl.text = pokemon.defense
    heightLbl.text = pokemon.height
    weightLbl.text = pokemon.weight
}

Now my question is: shouldn't we use DispatchQueue.main. and update the UI there like so?

pokemon.downloadPokemonDetails(completed: { (success) in
            if success
            {
                DispatchQueue.main.async {
                    self.updateUI()
                }
            }

The tutorial left it out and I'm not sure if DispatchQueue is needed here to update the UI. I know that updating UI in a background thread is bad practice so if anyone can shed some light on whether using DispatchQueue here to get the main thread is necessary or not, I would very much appreciate it.


Solution

  • If one does not want to read the whole comments section, I am posting here it as answer. Firstly, read Alamofire docs, which clearly states: "Response handlers by default are executed on the main dispatch queue."

    It means, you can call any UI related code in response block. If you still feel uncomfortable to rely on 3rd party lib doc, you can check by executing this swift3 snippet:

    if Thread.isMainThread { 
       print("Main Thread") 
    }
    

    xcode 9

    Starting from xcode 9 there is a built-in Main Thread Checker which detects invalid use of AppKit, UIKit, and other APIs from a background thread. Main Thread Checker is automatically enabled when you run your app with the Xcode debugger.

    If any part of your project contains invalid UI calls from background thread, you will see the following:

    enter image description here

    ** Demonstrated in Xcode Version 9.1 (9B55)