Search code examples
iosswiftmacosreactive-programmingcombine

Trying to inject values into a publisher, but receiving unordered values


This is an oversimplification of what I'm trying to achieve using combine.
I need to inject a value into a shared publisher if something happen. Here you see that if the number 2 is received by map I use the send command on the original publisher to inject the number 3.
I would expect to receive a sequence of number but instead I receive the number 3 before the event that triggered it.

let pub = PassthroughSubject<Int, Never>()

let pubSharered = pub.share().eraseToAnyPublisher()

let anyCanc = pubSharered
.map { value -> Int in
        switch value {
        case 2:
            pub.send(3)
            return value
        default:
            return value
        }
}.sink { (value) in
    print("Sink: \(value)")
}

pub.send(0)
pub.send(1)
pub.send(2)
pub.send(4)

The output is: 0,1,3,2,4 what I was expecting is 0,1,2,3,4.
Can someone explain it?


Solution

  • This seems like a use case for flatMap. You can flat map to a Publishers.Sequence<[Int], Never> like this:

    let anyCanc = pubSharered
        .flatMap { value -> Publishers.Sequence<[Int], Never> in
            switch value {
            case 2:
                return [value, 3].publisher // value, plus a 3
            default:
                return [value].publisher // change nothing
            }
    }.sink { (value) in
        print("Sink: \(value)")
    }