Generic networking layer using Combine in Swift UI.
In this short post, I will show you how to create a generic Networking API that you can reuse in your own implementations using generics and Combine. We won’t go in-depth of explaining elements of the Combine framework, instead, I will show you an example on how to use generics to boost your code reusability.
You will see here:
- Mix of generics and Combine Framework to create a reusable networking layer.
- Display elements from a network response in a SwiftUI list.
Don’t want to keep reading give me the code!. 😡
Let’s divide this into 3 simple steps…
Step 1: Build the generic networking layer.
Imagine you have to build an API that handles a request, handles errors, decodes the response, and also retries the network call if it fails 😳.
Well using Combine it will look as simple as this…
What do we have…
1 .- A protocol that has an URLSession
and a function that returns a Publisher
.
2 .- Extending the protocol so we can have a default implementation.
3 .- Here is how we improve our networking layer, if you don’t see it already I highly recommend checking this talk to see what is new in networking for iOS. We will use the dataTaskPublisher
from the Combine
framework instead of using a simple dataTask.
That’s it, now you have a generic API that can Decode any kind of object! 🙃
As you can see the code is more readable and concise, now let me show you how to use it in your own client…
Step 2: Adopting the Protocol in your own client.
What do we have…
1 .- The URLSession
to satisfy the CombineApi
protocol.
2 .- A couple of convenient initializers to facilitate instantiation.
3.- MovieFeed
is a model that contains everything we need to perform a URLRequest
, the code of it is irrelevant for this post because you can model it as you wish, but here is an idea.
4.- Here we call the execute
method passing as parameters a request, the meta-type of the object that we want to decode, and an integer to define the number of retries in case it fails.
With all of this, you can create a model that conforms to the ObservableObject
protocol to wrap your client networking logic, like this…
Step 3: Defining an ObservableObject.
1 .- A class that conforms to ObservableObject
, it will be able to notify updates before the object has changed.
2 .- An AnyCancellable
Subscriber to cancel the subscription on deallocation.
3 .- A Publisher
that streams the changes in the collection.
4 .- An instance of your client. 😉
5.- Combine uses the .sink
closure that attaches a subscriber with closures that gets executed on completion and when there is a new value available, by assigning the value to the movies
publisher, it will publish the changes 🚀.
The cool thing here is that you can also reuse this code in an UIKit application but just for fun let’s see how it will do it using SwiftUI…
- - Since iOS 14 you can build apps using just Swift UI, the
@main
keyword and theApp
protocol defines the starting point of your app. - Since iOS 14 you can use
@StateObject
as well as@ObservedObject
, both works in the same way but the first one has improvements in performance, theMoviesProvider
is the@ObservableObject
we just created. - Since iOS 14 you also need to have a struct that conforms to the
@Scene
protocol to “wrap” your application. - A navigation view, if you want to perform any navigation tasks.
- Big shout out to generics, if you didn’t notice already, they are everywhere! As you can see the
List
view is a container that takes an array of any kind of elements, a keypath (This id comes from theIdentifiable
protocol and every movie view model has one check it here.). List
has a closure that provides an element from the array and it returns any kind of view that conforms toView
protocol, if you are thinking inUIKit
this is the equivalent of a cell. (repo for the movie row implementation here.)
Here is the app! in the next post I will show you how to load images in the items of your list using combine and how to create a custom Image
view to cache them.
Here is the full repo. 🤖