Combine publishers merge, zip, and combineLatest on iOS

While working on an app where I needed to subscribe to multiple Combine publishers, I got confused about if I should use merge, zip or combineLatest. These publishers are quite similar with subtle differences. For making sure I never get confused about it, I am going to present examples in this week’s blog post.

Merge

Merge publisher just re-publishes any values received from any of the publisher. Useful when there are multiple sources of data we would like to combine into a single flow of updates.

@Published var state1 = "0"
@Published var state2 = "a"
func mergeExample() {
$state1.merge(with: $state2)
.sink { value in
print("sink", value)
}
.store(in: &cancellables)
print("will change state1 to 1")
state1 = "1"
print("will change state1 to 2")
state1 = "2"
print("will change state2 to b")
state2 = "b"
print("will change state1 to 3")
state1 = "3"
print("will change state2 to c")
state2 = "c"
}
/* output:
sink: 0
sink: a
will change state1 to 1
sink: 1
will change state1 to
sink: 2
will change state2 to b
sink: b
will change state1 to 3
sink: 3
will change state2 to c
sink: c
*/
view raw Merge.swift hosted with ❤ by GitHub

Zip

Zip waits until it has received at least one element from each of the underlying publisher, and then delivers the value as a tuple. If one of the publisher publishes multiple values, then the first received value is part of the tuple and other values are part of next tuples after that.

@Published var state1 = "0"
@Published var state2 = "a"
func zipExample() {
$state1.zip($state2)
.sink { value in
print("zip", value)
}
.store(in: &cancellables)
print("will change state1 to 1")
state1 = "1"
print("will change state1 to 2")
state1 = "2"
print("will change state2 to b")
state2 = "b"
print("will change state1 to 3")
state1 = "3"
print("will change state2 to c")
state2 = "c"
}
/* output
sink ("0", "a")
will change state1 to 1
will change state1 to 2
will change state2 to b
sink ("1", "b")
will change state1 to 3
will change state2 to c
sink ("2", "c")
*/
view raw Zip.swift hosted with ❤ by GitHub

CombineLatest

CombineLatest publishes a tuple whenever any of the underlying publishers emits an element. The tuple contains the latest value from each of the publisher.

@Published var state1 = "0"
@Published var state2 = "a"
func combineLatestExample() {
$state1.combineLatest($state2)
.sink { value in
print("sink", value)
}
.store(in: &cancellables)
print("will change state1 to 1")
state1 = "1"
print("will change state1 to 2")
state1 = "2"
print("will change state2 to b")
state2 = "b"
print("will change state1 to 3")
state1 = "3"
print("will change state2 to c")
state2 = "c"
}
/* example
sink ("0", "a")
will change state1 to 1
sink ("1", "a")
will change state1 to 2
sink ("2", "a")
will change state2 to b
sink ("2", "b")
will change state1 to 3
sink ("3", "b")
will change state2 to c
sink ("3", "c")
*/

If this was helpful, please let me know on Twitter @toomasvahter. Feel free to subscribe to RSS feed. Thank you for reading.