Combine: Combining Operators

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

Combine: Combining Operators

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 customise results to your liking.

For, exmaple 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 publiehrs 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 into 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 operatators or timers, how to use the dataTaskPublisher, how to combine publishers as well as how to debug Combine messages and much more.

To be notifed when new material is out, join our free mailing list.