Combine is Apple’s shiny reactive framework that provides a declarative Swift API for processing values over time. Or, as Apple puts it, it’s a way for iOS developers to ‘customize (the) handling of asynchronous events by combining event-processing operators’. Announced at WWDC 2019, Combine is still very much in its early stages and it’ll remain in beta until the release of the new SDK later this year. In this post, I’ll be giving you an introduction to Combine and what it has to offer.
Firstly, let’s take a look at how Combine works and behaves.
The Combine framework uses Publisher and Subscriber protocols. What are they?
Here’s what the official Apple documentation has to say about them:
Publisher: The Publisher protocol declares a type that can deliver a sequence of values over time. Publishers have operators to act on the values received from upstream publishers and republish them.
Subscriber: At the end of a chain of Publishers, a Subscriber acts on elements as it receives them. Publishers only emit values when explicitly requested to do so by subscribers. This puts your Subscriber code in control of how fast it receives events from the publishers it’s connected to’.
If you’re familiar with RxSwift, Publishers are essentially the same as Observables in that in order to be able to create a Publisher you must conform to protocol Publisher. Subscribers are the same as Observers in RXSwift, as they conform to protocol Subscriber. A Publisher can expose values that change over time and a Subscriber receives those updates.
A Subscriber contains the following receive methods:
func receive(subscription: Subscription)
Tells the Subscriber that it has successfully subscribed to the publisher and may request items.
func receive(Self.Input) -> Subscribers.Demand
Needs to be used to let the Subscriber know that the Publisher has produced an element.
func receive(completion: Subscribers.Completion<Self.Failure>)
Will be called when the Publisher has completed publishing, either normally or with an error.
Publishers can emit zero or more events over their lifetime.
So let’s go ahead and create a Publisher for a notification. We’ll first need to update our UI using a simple UILabel:
We should then be able to subscribe to the sequences by calling upon the following:
Lifecycle Cancel subscriptions: When a Subscriber is communicating with a Publisher it requests data because the Subscriber drives the closure execution. The Subscriber can cancel a subscription by calling .cancel().
If you look at the example above you can see that the NotificationCenter provides a Publisher that emits elements when broadcasting notifications.
There are many more Publisher types provided by Combine for free:
You can use an AnySubject instance to publish new elements imperatively with the send(_:) method.
Promises and Futures (PF) are constructs that allow the developer to promise that a result value will be provided at some point in the future and they’ll then specify what to do with the promised results when the future arrives.
Just provides a single result and then terminates it. This is used in error handling.
LoadRequest is a resource loader that acts as a publisher.
Published is a property wrapper that adds a Combine publisher to any property.
NotificationCenter.Publisher is a publisher that emits elements when broadcasting notifications. It conforms when Wrapped conforms to Publisher.
There are many, many more.
A Subject is a special type of Publisher that conforms to subject protocol. You can use it to ‘inject’ values into a stream by calling the send()method. You can also subscribe and dynamically add elements to it so it can be useful for adapting existing imperative code to the Combine model.
There are 2 types of subject:
currentValueSubject - ‘A subject that wraps a single value and publishes a new element whenever the value changes’.
PassthroughSubject - ‘A subject that passes along values and completion’.
Operators are classes that adopt both the Subscriber and Publisher protocol.
You can create chains of these together, for processing, reacting and transforming the data provided by a Publisher and requested by the Subscriber.
At some point, you will need to transform, combine or filter elements that a Publisher emits before the Subscriber receives them.
In Combine, you can achieve this by using an operator. Let's look at the map operator in order to transform Elements emitted from a Publisher before they reach their subscribers.
Imagine a transformation that multiplies each value of a sequence with 10 before emitting...
There are a huge amount of operators that you can use, as per Apple’s documentation on the subject, so I may dedicate another blog post in the future to sharing some examples.
Combine is built on multi-threading practices and thus allows publishers to specify the scheduler used when either receiving from an upstream publisher (in the case of operators) or sending to a downstream subscriber.
This is critical when working with a Subscriber that updates the UI, as it should always be called on the main thread.
You can do that by using .receive(on: RunLoop.main).
Combine is ideal for instances when your code needs to react to different inputs and combine those different inputs to then get an output - like when updating the UI after a user has filled in an email and password form. In that particular case, a Subscriber will observe the username and password fields and validate them when the input changes.
The result of that validation will be published into a stream that will then be observed by a view controller. When the user taps the login button, data will be passed to the API and will attempt to login. When the server responds asynchronously, we can observe the response and update the UI accordingly and store the token.
The framework can also be used to merge different network requests and decode their results. It’s also able to handle errors regarding each of the requests too.
Combine stands as a framework of composable components that can be combined to create workflows, in order to take advantage of asynchronous execution. You should be able to go away and experiment with Combine, as you’re now privy to the very basics of the framework.
It’s still early days but Combine promises to make the coding process much easier to create and maintain.
Are you excited to get to grips with Combine? Tweet us and we’ll be sure to retweet the responses!
We Are Mobile First is a digital product agency based in Barcelona helping to transform businesses in a mobile-first world. Follow us on Twitter, LinkedIn and Medium to be notified of our future posts and stay up-to-date with our company news.
(image credit: Apple Newsroom)