Swift Combine making serial sequence in order

Viewed 852

Here is the simple playground code that shows the two subscriptions in reverse order. How can I modify code so it will always print out 555? Currently it prints randomly 0 or 555 since operations are async. Please bear in mind that it is a concept, not an actual problem to solve, so putting all into one sink will not be a solution. Thanks

import Combine

class Foo {

    let subject = PassthroughSubject<Void, Never>()
    var myProperty = 0

    var bag = Set<AnyCancellable>()

    init() {
        subject
            .sink { _ in print(self.myProperty) }
            .store(in: &bag)

        subject
            .map { _ in 555 }
            .assign(to: \.myProperty, on: self)
            .store(in: &bag)

        subject.send()
    }
}

let testClass = Foo()
1 Answers

PassthroughSubject makes no guarantees about the order in which it will send values to its subscribers. You can't force an order, and the order could change in a future version of Combine.

One solution to store myProperty in its own subject, and subscribe to that subject to get the +555 values:

import Combine

class Foo {
    
    let subject = PassthroughSubject<Void, Never>()
    private var _myProperty = CurrentValueSubject<Int, Never>(0)
    var myProperty: Int { _myProperty.value }
    
    var bag = Set<AnyCancellable>()
    
    init() {
        _myProperty
            .sink { _ in print(self.myProperty) }
            .store(in: &bag)
        
        subject
            .map { _ in 555 }
            .assign(to: \.value, on: _myProperty)
            .store(in: &bag)
        
        subject.send()
    }
}

let testClass = Foo()
Related