Minimal Networking layer from scratch in Swift 4
How to build a declarative Networking layer in 118 relying on Codable, protocol oriented programming and URLSession without compromising modularity.
Introduction
Almost every iOS app has a networking layer in order to comunicate with a JSON Api.
There are some great libraries that we can use to write the code needed to work with that Api. But they either is bloated and has many methods that we will never use, or they are so lightweight that they don’t enforce a clear code structure.
If you aren’t willing to read the whole thing, I’ve packed the code in this article as a module and released it as a Cocoapod. Feel free to use it and contribute to the repo in case you need.
The Request process
This may be the silliest diagram I’ve ever done, but it has sense to start this explanation.
When describing a http request, we have to describe two parts.
- The Request: What does the networking layer need to know in order to dispatch the request
- The Response: What does the networking layer need to know in order to parse the response to make it valuable for the rest of the app.
In addition, there is another component that we will call “Dispatcher”, which is needed in order to dispatch the request to the server.
The Request
The first step to create a declarative layer is describing the concepts in terms of “what” instead of “how”.
So, what is a Request
? A request is an object that describes “what” is required to perform a http request. It includes:
- The url path of the resource that we are requiring.
- The HTTP method (get, post, put, patch, delete, etc.)
- The body parameters in case it is needed
- The request headers
In swift, this can be declared as a struct
The Response
When the request is resolved and the JSON is returned from the API, we need to parse it to actual models that make sense in the context of our app.
To accomplish that, we can take advantage of a recent feature of Swift: The Codable
protocol.
For instance, a User model can be described as:
Wrapping it up
In order to join Request and Response in something that acts as a glue, we are going to use protocol oriented programming.
We can define a protocol called RequestType
that associates a Request
with the matching response type (implementing Codable
)
The Dispatcher
Ok, so we have a RequestType
that joins the request data and the shape of the response of a certain request. We just need something that actually dispatches the request using the request data and parses the returning json to convert it to the models. That “thing” is called a Dispatcher
.
Lets take a look at the protocol describing the requirements:
The dispatcher can be implemented in very different ways. To make it lightweight, we are going to use the native UrlSession
. The code would look like this:
To use the dispatcher to dispatch the request, we are going to extend the RequestType
protocol to allow it to actually execute the requests:
Please note that the dispatcher is interchangeable, so you can use whatever you want in its place, as long as it conforms to NetworkDispatcher
protocol.
Example Usage
Three simple steps:
- Write a struct/class that conforms to
Codable
. - Write a struct/class/enum that conforms to
RequestType
. - Execute it!
Conclusion
I have been using this pattern for a long time in production environments, and I personally love it due to its natural simplicity. It just feels like the natual way of describing network layers.
I would really like if you try the library and make me know what you think about it.
Feel free to ask whatever you need
Thanks!