Implement a Networking Layer Using Combine in Swift 5
A flexible solution to copy and paste into your new app
In this article, we will learn how to architect and create an efficient and easy to use networking layer by leveraging Combine publishers, Codable, CustomStringConvertible protocol, and a custom Endpoint struct.
At the end of the tutorial, you will have a ready-to-use implementation that you can easily copy and paste in your app and expand it the way you want.
The full source code is available at the bottom of the article.
Before we dive into the code, let’s first outline all components of our networking layer:
- Endpoint — a handy
queryItemsproperties. By defining extensions on it, we can conveniently create a base URL of our REST APIs, define specific endpoints and headers (that will make more sense to you as we start implementing it, so don’t worry).
- Codable models — simple objects that can be created from JSON.
- Network Controller — responsible for working directly with
URLSessionTasks and decoding a
Codablemodel from the data. For example, it has a generic
get()method that returns a publisher containing a model.
- Logic Controller — abstracts the work being done by the network controller from the presentation layer (views/view controllers) and provides simple methods for querying models. For example, it may have a
getUsers()method that calls the required method of a network controller and returns an array of users.
We are going to use a free REST API called Dummy API:
Fake user data api - DUMMYAPI.IO
Full cycle REST production API server with fake data, 100 Users, over 800 posts, 1000 comments, 24/7 available for your…
Now let’s start creating each component, one by one.
We are going to fetch users from the Dummy API. The JSON looks like this:
So we create the following two structures:
Note that we conform to the CustomStringConvertible protocol to easily debug our objects. We have the following handy extension that alleviates the burden to define the
description property for each conforming struct:
With models done, now let’s move to another component.
Endpoint struct that we will extend to match specific API requirements:
Now, we need to create an extension in which we construct the
URL for the Dummy API and also define the
headers property containing an app ID (required by the Dummy API):
Now let’s define a few endpoints:
We are going to use only the first one. I have provided the latter two to show how we can conveniently add parameters and set the path.
Now, it’s time for the
First, let’s define a
As we can see, we have a method for querying a single Codable model.
Now we need to create a concrete implementation of the protocol:
Note how in just four lines of code, we do the following:
- Create and launch a
- Obtain the
dataif no error occurred
- Decode a model object
- Return a publisher containing either a model object or an error
We have the final component left — a
Because we want to fetch users, our logic controller will be called the
UsersLogicController. First, let’s start with a protocol:
We have the dependency on the
NetworkController and define three methods:
getUsers()— queries 20 users by default
getUsers(count: Int)— queries the specified
getUser(id: String)— queries one user matching the provided
The concrete implementation looks like this:
As we can see, we work directly with endpoints and call the required methods of the
NetworkController. By marking the class as
final, we signal to other developers that this class is not designed to be subclassed.
Finally, we can test what we have created.
Let’s initialize the
NetworkController and a
subscriptions property that will store our future subscription:
Now we can fetch the users as follows:
As expected, we see
User objects pretty-printed as expected:
The source code of the Xcode Playground is available in a gist.
Check out this great video by John Sundell on managing URLs and endpoints, which inspired this post:
Swift clip: Managing URLs and endpoints | Swift by Sundell
In this video, we'll take a look at three different ways to manage the URLs and server endpoints that a Swift app is…
Want to learn more about Combine? Check out my other relevant pieces:
- Use Combine to Write More Readable Swift Code
- Replace Delegation With Combine in Swift 5
- 7 Sequential Operators You Should Know From Swift Combine
- 6 Combining Operators You Should Know From Swift Combine
- Swift: 5 Transforming Combine Operators You Should Know
Thanks for reading!