Introduction to Combine framework in Swift
Understand the basics of the Combine framework with code examples
Combine is Apple’s framework for reactive programming introduced at WWDC19. It allows us to process values over time using declarative APIs that can work as an alternative to the delegate pattern or in-blocks callbacks.
Although, we can use Combine together with other patterns or architectures to solve specific tasks in our projects. In this article, I want to show you an introduction to the framework with some code examples so you can see the potential that Combine has.
There’re three main concepts in the Combine framework that we need to understand before we dive deep into it.
Publishers
It’s a protocol that defines the values type that are going to be emitted over time. The events that a Publisher can emit are a value, an error, and a successful completion.
The protocol has two associated types
that must be defined:
- Output: The value types that will be sent. It could be a String, an Int, a custom Struct, etc.
- Failure: The error type to use when we want to emit a failure event.
Subscribers
A Subscriber can receive the events that a Publisher emits and perform the task needed with those events.
It’s also a protocol and, as the Publisher, has two associated types
:
- Input: The value type that the Subscriber is going to receive.
- Failure: The error type when the Publisher emits a failure event.
Both the Input and the Failure must match the Publisher’s Output and Failure types.
Operators
There are methods that can transform the values that a Publisher emits. We can chain as many operators as we want. For example, if we’re making a network request and we get a 500 error, we could capture that error, transform it to a custom Error type, and send that value.
You can check the full list of the operators that Combine has here.
Combine in Action
Now that we have covered the basics, let’s jump into some code examples to see how Combine actually works.
We will be using AnyPublisher
type, which is an implementation of the Publisher
protocol that we can use to return the Publisher instance that we want. Also, the sink method allows us to process the values that the Publisher sends.
Convenience Publishers
We can take advantage of some of the built-in Publishers that Combine provides instead of creating our own. Let’s see the most common ones.
Just
Emits a value only one time, then finishes. This type of Publisher is useful when we want to replace an error with some default value.
Fail
The Publisher ends with a specific error. For example, if in our previous example we wouldn’t want to return a default value when getting an error but a specific error instead, we can use the Fail Publisher.
Future
It might or might not emit a value and finish or fail. It’s useful for asynchronous code, like API calls. We need to fulfill a promise with some result, it could be successful or failure. If the promise is fulfilled, that promise is sent to the subscriber.
Subjects
It’s a subclass of the Publisher protocol that can emit values on demand to the Subscribers by calling the send(_:)
method. The framework already has two Subjects implemented that are ready to go.
Imagine that we’re working on an application to see the live score and announcements of a soccer match.
A pretty simple struct that is built with a specific Subject. Once we create an instance, we can emit a new announcement by calling the sendAnnouncement
method. Also, we can tell the subscribers that the match ended or we can emit a custom error if something was wrong using matchEnded
and matchSuspended
methods.
PassThroughSubject
What the PassThroughSubject basically does, is emits new values to the subscribers without storing any state or values itself.
CurrentValueSubject
It’s very similar to PassThroughSubject with a key difference, CurrentValueSubject does store the actual value and it publishes it to the subscribers whenever that value changes. Because it stores the current value, any new subscriber will receive that value at the moment of the subscription.
Another difference is that CurrentValueSubject has an initial value with which we need to initialize the Subject.
Published Wrapper
By using the @Published
wrapper in any property, Combine will automatically create a Publisher for that property and it will emit the value whenever the property value change. We can access the Publisher with the $
operator.
The only restriction that we have is that @Published
can be used in classes, not in structs.
Summary
Combine is a powerful framework if we want to use reactive programming in our projects, but it comes with an expensive learning curve at the beginning. However, once you fully understand the basics it becomes easier to use.
Having said that, not every project is suitable for Combine, you need to be sure if you want to adopt this reactive approach or if any other architecture or framework fits better your project’s need.
If you’re interested in Combine you can check the WWDC sessions.