Chaining methods in swift Using Alamofire
Last day, when I was working on the api calls using almofire, I came across a weird looking method call which was something like creating an object of almofire and then calling a method with the object created ,followed by another method after a dot(.), followed by another method so far and so on…
The api call I was talking looks something like this:
Alamofire.request("https://httpbin.org/get")
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.responseData { response in
switch response.result {
case .success:
print("Validation Successful")
case .failure(let error):
print(error)
}
}
Here , we are calling a method called
request on the Almofire class. This is followed by a method called validate(statusCode:), then another method called validate(contentType:) . Then at last we can see a method called responseData with a trailing closure which returns the output of the api call.
How does it work?? Well, the logic is quite simple.
- Making functions chainable is quite easy and can allow us to write using an almost DSL-like syntax.
- We’ll add a new function that does something and then return
self. It's that simple.
Chaining methods example:
Let’s create an
APICaller class.class APICaller {
var url:URL?
var method = HTTPMethods.get
var params:[String:String]?
enum HTTPMethods: String { // http methods
case get = "GET"
case post = "POST"
case put = "PUT"
case patch = "PATCH"
case delete = "DELETE"
}
func urlString(_ urlString: String?) -> APICaller {
if let urlString = urlString {
self.url = URL(string: urlString)
}
return self
}
func method(_ method:HTTPMethods) -> APICaller {
self.method = method
return self
}
func parameters(_ params:[String:String]) -> APICaller {
self.params = params
return self
}
func response(response:@escaping([String:AnyObject]) -> Void) {
// create URLRequest with the http method, url, parameters etc and do the api call using URLSession method.. say use DataTask.
let resultDictionary = ["result":["Result values1","Result values2","Result values3","Result values4"]]
// let resultDictionary be the output of the API call made. Now, call the completion closure and pass the value .
//DispatchQueue.main.async {
response(resultDictionary as [String:AnyObject])
// }
}
}
An api call normally have aurl, anhttp methodandparameters.
If we use the class to make an API call,it will look something like this.
let params = [“key1”:”value1",”key2":”value2"]APICaller().urlString(“www.google.com").method(.post).parameters(params).response {
(resultDict) inprint(resultDict[“result”]!)}//----------------
// prints the following in console.
("Result values1",
"Result values2",
"Result values3",
"Result values4")
Let’s split up the above call.
- Create an instance of
APICallerclass. - Call
urlStringmethod with a string as parameter. This will set theurlproperty inAPICallerclass and returnself. - Call
methodmethod which set themethodproperty ofAPICallerclass and returnself. - Call
parametersmethod which sets the parameters for the api call and returnself. - Finally, call the method called
responsewhich has a trailing closure as parameter. Here, do the API call stuff and on success or failure, call the callback closure with the result object. Here the closure takes only a dictionary of typeDictionary<String,AnyObject>.
I
hope everything is clear. Either we can have a single init method with
all these parameters and call a method which in turn calls the api and
return the response. But, here the greatest advantage is that we need to
call any chaining method only when required. If we are doing a
get method call, we can skip the method method call as get is given as the default method inside the code. Also if parameters are not required, we may skip those too.Our objective is to write less code which makes more sense!!!
Enjoy!!


No comments: