Search code examples
iosswiftxcodeasynchronousgrand-central-dispatch

How to call GrandCentralDispatch properly


I am trying to load custom data type from my API and display it on my landing page of an iOS app.

As i understand, I should call something like:

override func viewDidLoad() {
  performSelector(inBackground: #selector(fetchJSON), with: nil)
  let myCustomDataType = //how so I get this back
  tableView.reloadData()
 //...
}

Obviously the declaration of fetchJSON should be in another file so I don't fill my Controller up with things it doesn't need to do. However I need this function to return a list of [MyCustomDataType] and display those on my landing page.

func fetchJSON() -> [MyCustomDataType] {
  //get api, fetch data, put it in my custom data type list
  return myCustomDataType
}

Do I use closures? Create a global [MyCystomDataType]. Or how do I achieve this? Be mindful of the task being async, since I display table cells kinda like facebook, or instagram news feed page.


Solution

  • If fetchJSON loads the data asynchronously you have to add a completion handler

    func fetchJSON(completion: @escaping ([MyCustomDataType]) -> Void){
        API.fetch { fetchedData in
            completion(fetchedData)
        }
    }
    

    Then call fetchJSON on a background thread and reload the table view on the main thread

    override func viewDidLoad() {
       DispatchQueue.global().async {
          self.fetchJSON { data in 
              DispatchQueue.main.async {
                  self.myCustomDataType = data
                  self.tableView.reloadData()
              }
          }
       }
    }
    

    Popular asynchronous APIs like URLSession and Alamofire perform their network requests on a background thread implicitly. If you are going to use one of them you can omit the first async block.

    performSelector is an outdated objective-c-ish API. Don't use it in Swift