CombineLatest multiple PassthroughSubject no output

Viewed 91
let p1: PassthroughSubject<Int, Never> = .init()
let p2: PassthroughSubject<Bool, Never> = .init()

var pub1: AnyPublisher<Int, Never> {
    return p1.eraseToAnyPublisher()
}

var pub2: AnyPublisher<Bool, Never> {
    return p2.eraseToAnyPublisher()
}

var sub: AnyCancellable?

sub = Publishers.CombineLatest(pub1, pub2).sink(receiveValue: { output in
    print("output: \(output)")
})

p1.send(4)
// nothing printed
p2.send(false)
// printed: output: (4, false)

why is there no output when p1 sends 4? How should I structure the code such that when either p1 pr p2 sends a value, there is an output?

1 Answers

The combineLatest operator can't emit something until every publisher it is observing emits something (a publisher that hasn't emitted a value doesn't have a "latest value" to emit.)

As you mention in comments, one way to get around this is to use a CurrentValueSubject so that there is a "latest value" for each child publisher.

Another way is to use .prepend to emit a value for combineLatest to use.

As in:

sub = Publishers.CombineLatest(pub1.prepend(0), pub2.prepend(false)).sink(receiveValue: { output in
    print("output: \(output)")
})
Related