Combine: Combining Operators

Combine: Combining Operators

With these short code snippets you will be able to combine operators when configuring publishers in Combine.

This brief overview will demonstrate some basic features that may come in handy when working with publishers in Combine, Apple's framework to handle asynchronous events by combining event-processing operators. The Publisher protocol declares a type that transmits a sequence of values over time that subscribers can receive as input by adopting the Subscriber protocol.

Using a sequence as values to publish, Combine allows typical operators available in Swift to shape the values that will be published or received. These operators can also be combined to customize results to your liking.

For, example you can use multiple prepend(_elements: Output...) operators to insert values into the sequence:

import Foundation
import Combine

let publisherA = (1...5).publisher
let publisherB = (500...510).publisher

    .sink {

Of, course this also works with the append(_elements: Output...)operator:

let publisherC = (1...10).publisher
let publisherD = (100...110).publisher

    .sink {

You can also use the .switchToLatest() operator to switch between differnet publisher, depening on your needs. Here, after publishers is receiving the publisher2 object as an event, it is switching the the latest received publisher, resuling in events from publisher1 no longer being received.

let publisherE = PassthroughSubject<String, Never>()
let publisherF = PassthroughSubject<String, Never>()

let publishers = PassthroughSubject<PassthroughSubject<String, Never>,Never>()

publishers.switchToLatest().sink {

publisherE.send("Publisher E - Value 1") //Publisher E - Value 1
publisherE.send("Publisher E - Value 2") //Publisher E - Value 2

publishers.send(publisherF) // switching to publisher 2
publisherF.send("Publisher F - Value 1") //Publisher F - Value 1
publisherE.send("Publisher E - Value 3") //

With the .merge(with other: Self) operator you can also merge publishers to emits an event when either upstream publisher emits an event. For this to work, all publisher have to be of the same type. For example:

let publisherG = PassthroughSubject<Int, Never>()
let publisherH = PassthroughSubject<Int, Never>()

publisherA.merge(with: publisherB).sink {

publisherG.send(10) //10
publisherH.send(2) //2

You can also combine different publishers by using the .combineLatest<P>(_ other: P) operator to create a publisher that receives and combines elements from this and another publisher. The values are submitted, however, only once values from all publishers have been sent. For example:

let publisherA1 = PassthroughSubject<Int, Never>()
let publisherB2 = PassthroughSubject<String,Never>()

    .sink {
        print("P1: \($0), P2: \($1)")

publisherB2.send("A") //P1: 1, P2: A
publisherB2.send("B") //P1: 1, P2: B

With the .zip<P>(_ other: P) operator you can couple publisher to emits pairs of elements from the upstream publishers as tuples. For example:

let publisher1A = PassthroughSubject<Int, Never>()
let publisher2A = PassthroughSubject<String, Never>() {
    print("P1: \($0), P2: \($1)")

publisher2A.send("3") //P1: 1, P2: 3
publisher2A.send("4") //P1: 2, P2: 4

Where to go next?

If you are interested in knowing more about working with Combine and the various operators available to shape the sequence of values send by publishers and received by subscribers, check our other articles on Combine that will be released over the next days and weeks.

They will cover how to work with filters, sequence, and transformation operators or timers, how to use the dataTaskPublisher, how to combine publishers as well as how to debug Combine messages, and much more.