Swift: Escaping closure captures non-escaping parameter 'onCompletion'
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() }}
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 theclosure is passed as an argument to the function, but is called afterthe function returns. When you declare a function that takes a closureas one of its parameters, you can write @escaping before theparameter’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)
Use this:
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()}}