I have two publishers, one that gathers messages based on a state, and the second which is a Timer. I want these to fire in order - so first gather data, then start a timer. How can I do this? This is my current code:
let messagesPublisher = OnboardingStateLogic.publisher(
forState: state,
nextState: nextState
)
messagesPublisher
.sink { completion in
print("completed")
} receiveValue: { [weak self] messages in
messages.forEach { message in
self?.queue.enqueue(message)
}
}
timer = Timer
.publish(every: 2, on: .main, in: .default)
.autoconnect()
.sink { _ in
self.dequeueMessages()
}
I ended up using Publishers.Zip
. This only publishes when both upstream publishers have outputted a value:
messagesPublisher.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] message in
self?.queue.enqueue(message)
}
).store(in: &cancellables)
let delayPublisher = Timer
.publish(every: 2, on: .main, in: .default)
.autoconnect()
.eraseToAnyPublisher()
.setFailureType(to: Error.self)
let delayedValuesPublisher = Publishers.Zip(messagesPublisher, delayPublisher).eraseToAnyPublisher()
delayedValuesPublisher.sink(
receiveCompletion: { completion in
switch completion {
case .failure(let error):
print("something went wrong", error)
case .finished:
break
}
},
receiveValue: { [weak self] _ in
self?.dequeueMessages()
}
).store(in: &cancellables)