Swift: Escaping closure captures non-escaping parameter 'onCompletion'

Answers here were right on adding @escaping before the completion handler parameter declaration, albeit shortly explained.

Here's what I was missing for the full picture, taken from Swift's documentation:

Escaping Closures

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

So basically, if you want a completion handler to be called AFTER the method returns, it is defined as escaping in swift, and should be declared as such:

func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse)

You have to mark both completion handlers with @escaping. Usually the compiler offers a fix

class RestApiManager: NSObject {
    static let sharedInstance = RestApiManager()

    let baseURL = "http://api.randomuser.me/"

    func getRandomUser(onCompletion : @escaping (JSON) -> Void) {
        makeHTTPGetRequest(path: baseURL, onCompletion: { json, err -> Void in
            onCompletion(json)
        })
    }

    func makeHTTPGetRequest(path: String, onCompletion: @escaping ServiceResponse) {
        let request = NSMutableURLRequest(url : URL(string: path)! as URL)

        let session = URLSession.shared

        let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
            let json:JSON = JSON(data as Any)
            onCompletion(json, error as NSError?)
        })
        task.resume()

    }
}

Tags:

Ios

Api

Get

Swift