I have these two methods in my API class to get data from an API:
func authenticateUser(completionHandler: (responseObject: String?, error: NSError?) -> ()) {
makeAuthenticateUserCall(completionHandler)
}
func makeAuthenticateUserCall(completionHandler: (responseObject: String?, error: NSError?) -> ()) {
Alamofire.request(.GET, loginUrlString)
.authenticate(user: "a", password: "b")
.responseString { request, response, responseString, responseError in
completionHandler(responseObject: responseString as String!, error: responseError)
}
}
Then in another class i use the following code to access the data:
API().authenticateUser{ (responseObject, error) in
println(responseObject)
}
The code is working but i don't understand it completely.
Alamofire is a networking library written in Swift. You use it to make HTTP(S) requests on iOS, macOS and other Apple platforms. For example, to post data to a web-based REST API or to download an image from a webserver. Alamofire has a convenient API built on top of URLSession (“URL Loading System”).
Advantages of Using AlamofireUsing Alamofire will give a cleaner project. API call interactions (POST/GET/PUT/etc.) will be easier and more understable. Alamofire simplifies a number of common networking tasks that makes development faster and easier.
Networking in Alamofire is done asynchronously. Asynchronous programming may be a source of frustration to programmers unfamiliar with the concept, but there are very good reasons for doing it this way. None of the response handlers perform any validation of the HTTPURLResponse it gets back from the server.
completionHandler
is a closure parameter. As Swift documentation says:
Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.
So, what a closure is used for is to add some functionality of your own that you want to add to the execution of your function.
In your case, you call authenticateUser
and you pass a closure that receives (responseObject, error)
and executes println(responseObject)
. authenticateUser()
receives your closure under the completionHandler
parameter and it then calls makeAuthenticateUserCall()
passing your completionHandler
closure to it.
Then again, looking at the definition you can see func makeAuthenticateUserCall(completionHandler: (responseObject: String?, error: NSError?) -> ())
that means that like authenticateUser()
makeAuthenticateUserCall()
is a function that receives a closure as a parameter, under the name of completionHandler
. makeAuthenticateUserCall()
makes a network request using AlamoFire and you capture the response under a closure again that you pass as parameter of the responseString()
method. So you have:
//here you call authenticateUser with a closure that prints responseObject
API().authenticateUser{ (responseObject, error) in
println(responseObject)
}
Then:
//authenticateUser receives your closure as a parameter
func authenticateUser(completionHandler: (responseObject: String?, error: NSError?) -> ()) {
//it passes your closure to makeAuthenticateUserCall
makeAuthenticateUserCall(completionHandler)
}
//makeAuthenticateUserCall receives your closure
func makeAuthenticateUserCall(completionHandler: (responseObject: String?,
error: NSError?) -> ()) {
Alamofire.request(.GET, loginUrlString)
.authenticate(user: "a", password: "b")
//here you pass a new closure to the responseString method
.responseString { request, response, responseString, responseError in
//in this closure body you call your completionHandler closure with the
//parameters passed by responseString and your code gets executed
//(that in your case just prints the responseObject)
completionHandler(responseObject: responseString as String!, error: responseError)
}
}
For more information read the documentation: Swift Closures
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With