While I was going through on how to make HTTP calls in Swift with Alamofire and subsequent URLSession tutorials, the HTTP calls looked something like,
While Alamofire does a pretty impressive job in cutting down a lot of the boilerplate, I soon realised that for projects with a lot many HTTP calls, maintenance of the API functions could be a lot easier if the generation of the Request URL and processing of response in completionHandler
are separated.
Being an Android developer, I’m very used to how Retrofit (Android’s goto Networking Library) lets us separate the HTTP call URL generation and underneath calling of functions from the responseListener
. Something like,
interface
are nothing but protocol
and each function represents the entirety of an HTTP call. All you need to do is call the function which will return an Observable
of the Response. Neat and simple right.
What Retrofit in Kotlin/Java does under the hood is that, for each of the function annotated with @GET or @POST
, the compiler synthesises all the required boilerplate to convert them into full-fledged HTTP calls with callbacks.
I was wondering if something like this could be done in Swift too and then I struck gold when I came across@propertyWrapper
in Swift. The official documentation it reads,
A property wrapper adds a layer of separation between code that manages how a property is stored and the code that defines a property.
For example, if we wanted to have String fields to always return value in the “CamelCased” format, we can write a @propertyWrapper
as follows,
The parallel I could draw in Kotlin would be either the custom getters and setters or even better, Property Delegates. In Kotlin, the above example would look something like this,
Using @propertyWrapper
we would try achieving a Retrofit-like syntax for our Alamofire boilerplates. Something like,
Let’s begin by typealias
ing our completionHandler
closure to Observer<T>
.
Next, let us implement a GET
struct as a @propertyWrapper
.
So what is going on here,
1. we have a local variable url
which is being set at init
.
2. the calculated value wrappedValue
is of type Observer<T>
which is going to behave as our completionHandler
from wherever we make the HTTP call.
3. inside the get
we return a closure
where the entire Alamofire boilerplate resides. So, every time I fetch the variable which has been tagged with this @GET
propertyWrapper, all I’ve deal it is the completionHandler
in the closure without worrying of the underneath HTTP call boilerplate.
So now, we can ‘declare’ our HTTP calls and use them with minimal code as follows,
So…
Though this example showed the implementation of a wrapper @GET(:url)
is a small portion of all the possible types of HTTP calls. The main reason for me to write this up was to demonstrate how @propertyWrapper
can be used to do a lot of heavy lifting to make our code more readable and manageable in the long run.
I’m still very new to iOS and working my way through it. So, if you have any suggestions or corrections feel free to reach me on Twitter or let me know in the comments below.
Also, I love reading about Monster Hunter and the vast foray of ecological varieties it provides. I’ve started maintaining a personal collection of ecology and lores from various sources I come across. Interested people do give it look 🐲