Search code examples
jsonswiftapiasynchronouscompletion

Swift: completion handler after network request


I know, there are lots of similar threads regarding asynchronous functions and completion handlers in Swift... But after reading quite a lot of them, I still can't figure out how to process the responded data of a network request and save certain values within global variables.

Here is my code (yes, I'm a Swift rookie):


let equitySymbol = "AAPL"
var companyCountry = String()

func sendRequest(_ url: String, parameters: [String: String], completion: @escaping ([String: Any]?, Error?) -> Void) {
    var components = URLComponents(string: url)!
    components.queryItems = parameters.map { (key, value) in
        URLQueryItem(name: key, value: value)
    }
    components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
    let request = URLRequest(url: components.url!)
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        
        if let data = data,
            let response = response as? HTTPURLResponse,
            (200 ..< 300) ~= response.statusCode,
            error == nil {
            let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
            completion(responseObject, nil)
        }
        else {
            completion(nil, error)
            return
        }
    }
    task.resume()
}

sendRequest("myUrl", parameters: ["token":"..."]) { (responseObject, error) -> Void in
    
    if let responseObject = responseObject, error == nil {
        companyCountry = responseObject["country"] as! String
    }
    else {
        print(error ?? "Details Not Available")
        return
    }
}

print(companyCountry)

As you may assume, my variable "companyCountry" is still nil after my func "sendRequest" has been called (playground), when it should be "US" in this case. What's my mistake? Thanks a lot for your help!!!


Solution

  • A successful network request can take a long time. Usually it's much less than a second, but up to 60 seconds is possible. Even if it is just a millisecond, you are printing companyCountry a loooooong time before the callback function of the network request is called.

    If you want to print companyCountry for debugging purposes, print it in the callback. If you want to keep it, store it into a permanent location in the callback.