Steve Steve - 1 month ago 11
Swift Question

Need clarification regarding closures/completion handlers

I have been following a video tutorial, and have written the following code:

func downloadWeatherDetails(completed: ()->() ) {

let currentWeatherURL = URL(string: CURRENT_WEATHER_URL)!

Alamofire
.request(currentWeatherURL)
.responseJSON(completionHandler: { response in
let result = response.result
print(result)
})
completed()
}


So basically, my understanding is as follows. The
.responseJSON
handler lets you call code after the request has been fired. It allows you to specify a
completionHandler
, which in my case, is the closure:

{ response in
let result = response.result
print(result)
}


However, what I don't understand is what the "response" keyword actually signifies. I researched the usage of closures and saw that the syntax is:

{(param) -> returnType in { code here }


Thus, is the "response" keyword a parameter? If so, how is it being declared and where is the data coming from? How is the data passed into the "response" object? Also, why is only one parameter allowed? The code did not work if I made it as follows, for example:

{ (response, test) in
let result = response.result
print(result)
}


I would really appreciate a thorough explanation on this as I've found no help elsewhere online. I've gone through Apple's "The Swift Programming Language", a multitude of different explanations, and similar questions, but still do not understand completely.


Just to clarify, I do not believe my question is a duplicate since my question revolves primarily on the captured value stored in
response
rather than the syntax of closures as a whole. I went through the linked question while trying to figure out my own problem, but it did not help me sufficiently.

Answer Source

Swift closures are defined as:

{ (parameters) -> return type in
    statements
}

That is, the names in parenthesis are the variables the closures has captured the -> type is the optional return type (optional because the compiler can usually infer it). Alamofire's responseJSON method captures a DataResponse<Any> parameter, which you can name whatever you want, but which is usually just named response. You can then access it inside that closure.

Also, your completed() call should be inside the responseJSON call, not outside, otherwise it just gets called immediately.