Swift Combine - combining publishers without waiting for all publishers to emit first element

Viewed 730

I'm combining two publishers:

let timer = Timer.publish(every: 10, on: .current, in: .common).autoconnect()
let anotherPub: AnyPublisher<Int, Never> = ...

Publishers.CombineLatest(timer, anotherPub)
    .sink(receiveValue: (timer, val) in { 
      print("Hello!")
} )

Unfortunately, sink is not called until both publishers emit at least one element.

Is there any way to make the sink being called without waiting for all publishers? So that if any publisher emits a value, sink is called with other values set to nil.

1 Answers

You can use prepend(…) to prepend values to the beginning of a publisher.

Here's a version of your code that will prepend nil to both publishers.

let timer = Timer.publish(every: 10, on: .current, in: .common).autoconnect()
let anotherPub: AnyPublisher<Int, Never> = Just(10).delay(for: 5, scheduler: RunLoop.main).eraseToAnyPublisher()

Publishers.CombineLatest(
    timer.map(Optional.init).prepend(nil),
    anotherPub.map(Optional.init).prepend(nil)
)
.filter { $0 != nil && $1 != nil } // Filter the event when both are nil values
.sink(receiveValue: { (timer, val) in
    print("Hello! \(timer) \(val)")
})
Related