Swift Protocol Oriented Network Layer

Richa Srivastava
6 min readApr 11, 2021

In WWDC 2015, Apple announced that Swift is protocol oriented langueage. And i would really recommend everyone to go and watch this WWDC video on protocol orineted programming in swift by Dave Abrahams. I really love his reference to crusty character and the way he explains everything makes it easier to understand. One thing Dave said in his talk is that in Swift Always start with Protocols. Well, thats what we will do here! we will start with Protocols for our network layer.

So what do we know about making a network call —

  1. we know we will have a URL through which we make a request.
  2. And then with that request and make an API call using URL session
  3. And in the end once we have our data which we can parse.

So exactly like below —

Request(make request) — → API CALL —→ Response (parse response)

Lets replicate it in Programming —

We will have RequestHandler protocol, which will have one function to make request and we will have one ResponseHandler protocol, which will have one function to parse response. And we will have APILoader struct which will have a function to make API call with the help of RequestHandler and ResponseHandler protocols.

RequestHandler — — → APILoader — — — → ResponseHandler

We will talk about APILoader in the end but first lets talk about APIRequest and APIResponse protocols.

APIHandler.swift

APIHandler.swift

RequestHandler has one function makeRequest, which accepts a generic param and returns URLRequest. associatedType in the way we can make protocols generic.

ResponseHandler has one function parseResponse, which accepts data of Data type and response of HTTPURLResponse. Both of these we get after a successful api call. Parsing can also throw an error. And again the return type here is an associatedType which makes it generic.

We have created a typealias APIHandler here to refer both RequestHandler & ResponseHandler.

We can add more helping methods in our RequestHandler & ResponseHandler using protocol extension.

RequestHandler+Extension.swift

RequestHandler+Extension.swift

In RequestHandler extension, we have written here two helping method, one is to setQueryParams and other one is to setDefaultHeaders for our request.

ResponseHandler+Extension.swift

ResponseHandler+Extension.swift

In ResponseHandler extension, we have written a method to parse data and return a generic response. Here return type T confirms to codable, means our parsed data will confirm to codable. With a struct ServiceError, we will handle error in our network layer.

Now lets come to the APILoader part of our network layer. This is where we will have our main code to make API call.

APILoader.swift

APILoader.swift

Lets understand this APILoader properly —

  1. APILoader struct has two variables, one is apiHandler which is a of a generic type of our APIHandler protocols. Means with this variable we will be able to access all the method of our APIHandler protocols(which are RequestHandler & ResponseHandler).
  2. The other variable is urlSession, we are injecting urlSession session here instead of using it directly so that later on it would be easier to test this.
  3. In line 15, we are injecting apiHandler and urlSession, for better testability
  4. In line 20, for loadRequest function we have two params, one is requestData, which will be of type T.RequestDataType, here T confirms to APIHandler so it has access to associatedType of the protocols.
  5. And the second param is completionHandler, which will be called when API call has completed and we have our data or error. completionHandler also takes two param one of type T.ResponseDataType and one is ServiceError.
  6. In line 21 we call, makeRequest function of apiHandler, which returns a URLRequest.
  7. In line 22, we will make the API call using urlSession and urlRequest.
  8. In line 26 & 31, we have guard statement to check if API request was failed due to some reason, in that case we call completionHandler with error.
  9. From line 36 to 41, we parse our response with apiHandler parseResponse function and return the parsed response through our completion handler in line 38.

That’s it, we have a complete flow of our network call, from making request to making a api call and then parsing the response. Now there are some helping enum and struct we need to write to help make our URL for API call.

Helping Enum & Struct to make complete endpoint URL —

APIEnvironment.swift

APIEnvironment.swift

We have this APIEnvironment enum to get selected environment like development, staging and production and to get our baseURL. baseURL will consist of common domain for all your API’s and subdomain and in somecase route as well. Here i have used unspalsh api for my demo application.

APIPath.swift

APIPath.swift

APIPath struct will have all the api paths as given above. the code itself is self explainatory here. In demo application we are making call to one unspalsh API only which returns some images. If we have more API’s in app then we will add more variable like gallery in our APIPath struct.

Our network layer group looks like this —

Networking Group

Implementation

Now let see the implementation, As i said in demo application we will make an API call to a unspalsh gallery API to get some images and show those images in a UICollectionView. As we follow good coding style we will have everything in MVVM approach.

First we will make a GalleryAPI struct, which will implement APIHandler and handle request and response for our API call —

GalleryAPI.swift

As GalleryAPI confirms to APIHandler it has to implement its methods, which are makeRequest and parseResponse. In makeRequest function we are basically generating URLRequest for our API calls. We get url from APIPath and then we use the setQueryParams method of RequestHandler protocol to set the query params, and similarly use the setDefaultHeaders method to set default headers. As we can see here, the params dictionary confirms to the RequestDataType associatedType here.

In parseResponse method, we just simply call the defaultParseResponse method of ResponseHandler extension method, you can write your own code to do some complex parsing as well. And here the GalleryModel is a Codable model which can we used as we had ResponseDataType associatedType as return of this method in our protocol. This makes our parsing method generic for all the codable response model!!

GalleryViewModel.swift

We will make our final API call from this struct which is a view model of our MVVM pattern.

GalleryViewModel.swift

This is very simple, we just have one function which makes our API call.

  1. First we get our URLRequest through GalleryAPI
  2. Then we create apiLoader instance by calling APILoader class with request
  3. In the we just make a simple call to our loadAPIRequest method of APILoader, which gives us the response model (that is GalleryModel here) in the completion block.

And this is it!! We have successfully used our Networking Layer.

You can find the complete source code here. Apologies for any spelling or grammatical mistakes.

Video tutorial — https://www.youtube.com/watch?v=RDQqd2_AyA0

Happy Learning!!

--

--

Richa Srivastava

iOS Developer, YouTuber, Flutter enthusiast, Blockchain Enthusiast