Search code examples
swiftchainingcompletionhandler

How to chain functions with a completion handler in Swift?


I am chaining some functions together and I can't figure out how to call a completion handler with a return value once all the functions are done running.

func getAirQuality(completion: (aqi: Int?) -> Void) {
    callAPI()
}

private func callAPI() {
    // ... get data
    self.parseDataForAQI(data: data)
}

private func parseDataForAQI(data: Data) {
    let aqi = aqi
    // Send aqi up to completion handler in getAirQuality
}

So that when everything is said and done I can just do something like this:

getAirQuality(completion: { aqi -> Void in {
    // Do something with aqi
})

Solution

  • My first assumption is that your first 3 functions are part of a class. If so, one approach is to save the completion handler as an instance variable.

    class AirQualityProvider {
        var aBlock: ((Int?) -> Void)?
    
        func getAirQuality(completion: @escaping (Int?) -> Void) {
            aBlock = completion
            callAPI()
        }
    
        private func callAPI() {
            let data = Data()
            parseDataForAQI(data: data)
        }
    
        private func parseDataForAQI(data: Data) {
            let aqi = 1
            if let completion = aBlock {
                completion(aqi)
            }
        }
    }
    

    Here's an example of a caller as written in a playground.

    let aqp = AirQualityProvider()
    aqp.getAirQuality { (value) in
        if let value = value {
            print("Value = \(value)")
        }
    }