
Let’s Start With Combine framework.
Combine framework is a new framework that Apple unveiled in this year’s WWDC. Combine helps developers work with synchronous and asynchronous tasks.
Customize handling of asynchronous events by combining event-processing operators.
What is Combine?
Combine is Swift declarative framework for processing values over time [1]. It imposes functional reactive paradigm of programming, which is different from the object-oriented one that prevails in iOS development community.
The Combine framework can be compared to frameworks like RxSwift and ReactiveSwift (formally known as ReactiveCocoa). It allows you to write functional reactive code by providing a declarative Swift API.
Reactive means programming with asynchronous streams of values.
Functional programming is all about programming with functions. In Swift functions can be passed as arguments to other functions, returned from functions, stored in variables and data structures and built at run time as closures.
In declarative programming style you describe what the program does, without describing the flow of control. In imperative style you write how the program works by implementing and handling a series of tasks. Imperative programs rely primarily on state, which is usually modified with assignments.
Programming with Swift Combine framework is both declarative, reactive and functional. It involves chaining functions and passing values from one to the other. This creates the streams of values, flowing from the input to the output.
Combine Concept
Combine framework is divided in 3 main components:
- Publisher: it triggers sequence of value or new state through its Output.
- Subscriber: it subscribes to a Publisher to get notified of any changes made using its Input.
- Operators: it represents the layer in between for any transformation or manipulation of data from Publisher output to a Subscriber input as middle steps.

And even shorter:

Publisher
Publisher is responsible to emit sequence of values. It also handle different kind of messages:
- subscription — that’s the first event emitted between publisher and subscriber
- value — any kind of elements emitted
- error — the sequence finished by an error triggered
- completion — the sequence finished successfully.
Subscriber
On the other side, Subscriber can receive emitted elements from a Publisher.
receive(subscription:)notify it subscriber has successfully subscribed to publisherreceive(_:)for any new element emittedreceive(completion:)when sequence finished successfully.
Let’s see now how they works together.
Let’s start with a simple example. I would like to detect when the application changes of state between background and foreground. To do so, we’ll use NotificationCenter for that.
Apple documentation mentioned that NotificationCenter is one of the Foundation types that will support with Combine, but as it’s not done available yet, let’s see how we can do our own.
Starting with the publisher, the element triggering the changes will be NotificationCenter, so we can extend it to create a publisher from it.
import Combineextension NotificationCenter {
struct NotificationPublisher: Combine.Publisher {
// implementing Publisher protocol
typealias Output = Notification
typealias Failure = Never
let center: NotificationCenter
let name: Notification.Name
let object: Any?
func receive<S>(subscriber: S) where S : Subscriber,
NotificationPublisher.Failure == S.Failure,
NotificationPublisher.Output == S.Input {
// letting subscriber know subscription started
subscriber.receive(subscription: Subscriptions.empty)// observing notification, any new element would be forwarded to subscriber
center.addObserver(forName: name, object: object, queue: nil) { (notification) in
let _ = subscriber.receive(notification)
}
}
}func publisher(for name: Notification.Name) -> NotificationPublisher {
return Publisher(center: self, name: name, object: nil)
}
}
So far, I only create a Publisher struct for the NotificationCenter matching Combine protocol.
For any new elements subscribing to this publisher, it will create a notification observer that will forward the changes. In short we wrapping NotificationCenter with Combine framework.
I’ve also added a small method to make it more handy to use.
let backgroundPublisher = NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)Our publisher is ready, let’s add a subscriber to it.
The simplest one might be using sinks to use a closure as subscription.
backgroundPublisher.sink { notification in
print("Entered in background")
}Another way to get those changes is to use Subject protocol. Behaving as a Subscriberbut also Publisher, it can capture changes and forward them. For that, I’m going to use PassthroughSubject, a subject that passes along values and completions.
let subject = PassthroughSubject<Notification, Never>()
backgroundPublisher.subscribe(subject)let cancellable = subject.sink { _ in
print("Entered in background)
}
But what about operators?
That’s where it can get quite interesting. We actually can transform the values along the subscription. Let’s see how
First let’s create two publishers foreach notification. I’ll add an operator to transform the event into a String message.
let backgroundPublisher = NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)
.map({ _ in "Did enter background" })
let foregroundPublisher = NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)
.map({ _ in "Will enter foreground" })Then, I’m going to merge both publisher using Publishers.merge to create on sequence of String coming from both to keep only one subscription.
Publishers.Merge(backgroundPublisher, foregroundPublisher)
.sink(receiveValue: { message in
print(message)
})Here is my output in my console.
> Will enter foreground
> Did enter background
> Will enter foregroundI could have also chain it all together and avoid to have different instantiation.
NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification) // publisher
.map({ _ in "Did enter background" }) // operator
.sink(receiveValue: { print($0) }) // subscriberConclusion
we’ve seen how Publisher and Subscriber work, how to use Subject as middle ground element and how to transform and combine events using Combine operators.The basic principles are explained and there’s a lot more to cover. Therefore, I encourage you to start exploring Combine yourself!
Also, the following WWDC sessions are a great start to give yourself some more background information:
You can contact us on Twitter, Linkedin.
Happy coding!
