WWDC 2019

Step into Swift Combine

Mohammed Rokon Uddin
Monstar Lab Bangladesh Engineering
6 min readAug 27, 2019

--

What is Combine?

A unified declarative API for processing values over time.

Often in our code, we have many places where we have some sort of value or event Publisher and some Subscriber is interested in receiving values from that Publisher. And some interested party comes along and establishes a connection between these Publisher and Subscriber. Once the connection is established, the Subscriber sometimes declares that they are interested in receiving values from that Publisher (upstream), after which the Publisher is free to begin sending values to Subscriber (downstream). This goes on until either the Publisher decides to stop sending values, whether because it finished or there was some sort of failure, or by someone choosing to cancel the subscription. This general shape of communication appears throughout our software, whether it’s callbacks or closures or any other situations where there’s asynchronous communication. — Combine in Practice, WWDC 2019

This is the Pattern that Combine is all about, WWDC 2019

Key Concepts

Combine has following three concepts: Publishers, Subscribers, and Operators .

Publishers

Publishers are the declarative part of Combine’s API which describe how values and errors are produced and allow registration of a Subscriber to receive these values over time. They specify two associatedTypes and a key function as shown below:

Publisher protocol. WWDC 2019
  • Output is the type of value Publisher it produces.
  • Failure is the kind of errors that Publisher produces. If Publisher does not produce an error, then we can use type never for that associated type.
  • subscribe<S: Subscriber>(_ subscriber: S) is the key function that describes how to attach a Subscriber to a Publisher with the generic constraints that the associated types must match the Subscriber’s Input to Publisher’s Output, and the Subscriber’s Failure to Publisher’s Failure.

Here are some additional convenience publishers:

Just: It provides a single result and then terminates, it takes a failure type of <Never>

Future: A future is initialized with a closure that eventually resolves to a single output value or failure completion.

An example of Future

Published: A property wrapper adds a Combine publisher to any property.

Published wraps the variable, address, and will trigger events whenever the variable is mutated. Any subscriber(s) subscribing to the property will also receive any initial value being set upon the property’s initialization.

The below example is the implementation of Publisher protocol:

Implementation of Publisher Protocol

Subscribers

Subscribers are the counterparts of Publishers. They receive values, including the completion if the Publisher is finite. As Subscribers usually act and mutate state upon receipt of values, so they are reference types in Swift; in other word, they are classes. Below is the protocol of Subscriber:

Subscriber protocol. WWDC 2019

Subscriber has two associatedTypes as shown above. One is Input and the other is Failure. Subscriber has three well-defined event functions to receive a subscription, values and a completion as described below:

  1. A Publisher will call receive(subscription: Subscription) just once in response to a subscribe call.
  2. A Publisher can then call receive(_ input: Input) to provide values to the Subscriber.
  3. Once the Publisher has finished or a failure has occurred it sends at most a completion signal and no further values are emitted by a Publisher once that completion has been signalled.

There are two special Subscribers that takes burden from us:

  • sink(receiveCompletion:receiveValue:): Sink takes two closures. receiveCompletion executes upon subscribers completion and it is an enum that indicates whether the publisher finished normally or failed with an error and receiveValue triggers every time it receives an element from subscribed publisher.
Example shows an uses of sink
  • assign(to:on:): It immediately assigns every element it receives to a property of a given object using key path to indicate the property
Example shows an uses of assign

Operator

While working with Combine we often come to a scenario where output of the Publisher does not match the input of the Subscriber. Operators are the real saviors for such cases. They subscribe to Publishers (upstream), describe a behavior for changing values and then send the result to a Subscriber (downstream). Based on actions, Operators can be divided into the three following types:

1. Transformation Operators:

  • map: it operates just like Swift standard library map, except it operates on Publishers.
Marble diagram of map
  • flatMap: it tears down an observable sequence where elements of the observable itself are observables and merges the resulting observable sequences into one observable sequence. flatMap is mostly used in error handling scenarios.
Marble diagram of flatMap

2. Combination Operators:

  • merge: it combines multiple Observables into one by merging their elements
Marble diagram of merge
  • combineLatest: it combines the latest elements from two or more Publishers when any one of the Publishers emits an element.
Marble diagram of combineLatest
  • zip: this is similar to Combine Latest but unlike Combine Latest Zip waits for each Publisher to emit new elements.
Marble diagram of zip

3. Filtering and other Operators:

There are a lot more operators like filter removeDuplicates, debounce, count, contains and more which are self explanatory. I encourage you to go to Apple’s documentation and try some yourself.

Lot more Operators, WWDC 2019

Subject

Subjects are special types of Publisher in Combine in which we can subscribe as well as send events to them dynamically.

Subject Protocol, WWDC 2019

As shown in the above image, Subject describes two functions. One is to send value and other is to send completion with failure.

Combine provides two very handy subjects:

  • PassthroughSubject: It sends every element after subscription.
  • CurrentValueSubject: It behaves same as the PassthroughSubject but unlike PassthroughSubject, CurrentValueSubject stores the most recent elements and send to new subscribers.

Scheduler

  • receive: it takes a single required parameter (on:) which accepts a scheduler, and an optional parameter (optional:)
examplePublisher.receive(on: RunLoop.main)
  • subscribe: Subscribe defines the scheduler on which to run a publisher in a pipeline.
networkDataPublisher     
.subscribe(on: backgroundQueue) // 1
.receive(on: RunLoop.main) // 2
.assign(to: \.text, on: nameLabel) // 3
  1. The subscribe call requests the publisher (and any pipeline invocations before this in a chain) be invoked on the backgroundQueue.
  2. The receive call moves the data to the main thread to update the UI elements
  3. The assign call uses the assign subscriber to bind data to a KVO compliant object.

AnyCancellable

AnyCancellable is used to keep the reference of a subscriber so that we can clean up the subscriber on deallocation.

var cancellable: AnyCancellable?let sinkSubscriber = aPublisher
.sink { data in
print("received ", data)
}
cancellable = AnyCancellable(sinkSubscriber)

Source Code:

Related Articles:

Using Combine

Problem Solving with Combine Swift

Getting started with the Combine framework in Swift

RxMarbles

Conclusion

Combine is a very powerful framework, introduced in Swift 5.1. It enables developers to dive into reactive programming. Apple ingeniously designed this language feature which goes hand in hand with Apple’s new declarative UI framework SwiftUI yet keeping UIKit unchanged.

Though Combine itself is a huge topic to write on, in this article I have provided explanations and covered the basics to start with.

Later I have tried to cover most commonly used keywords in Combine with diagrams and code snippets.

Finally, I shared a working example of Combine with SwiftUI.

I hope that you have enjoyed this article. I encourage you to read my other articles on Swift Type Erasure, Custom UIView from .xib and TableView Prefetching DataSource using Swift

Thank you all for your attention 🙏🏻. Feel free to tweet and get connected.

Visit our website to learn more about us:
www.monstar-lab.co.bd

--

--

Mohammed Rokon Uddin
Monstar Lab Bangladesh Engineering

[ Apple Platform Developer | Tea & Coffee Brewer ☕️ | Occasional Chef 👨‍🍳 | Soccer Player ⚽️ ]