Home > Enterprise >  Swift Combine prevent initial value from triggering sink and prevent duplicates at the same time?
Swift Combine prevent initial value from triggering sink and prevent duplicates at the same time?

Time:11-16

I have a model that has a myState Bool and in a controller I sink to it like this:

model.$myState
.dropFirst()
.removeDuplicates()
.receive(on: RunLoop.main)
.sink { [weak self] myState in
    print("myState: \(myState)")
 }.store(in: &subs)

myState is initialized at init as false:

@Published private(set) var myState:Bool = false

I am trying to understand how to avoid the initial sink trigger to happen. I only want the sink to call when myState changes value. So if in the model I set it to false when already false, I do NOT want the sink to call. I can achieve that by with the .removeDuplicates(), but I still get the initial sink call. So then I added the .dropFirst(). With that in I do not get the initial sink call, but, the first time I set myState to false (when already false) sink is called even though myState was already false.

So, in short:

  • I only want sink to trigger when myState changes from false -> true or from true to false
  • do not want sink to trigger when I setup the sink (dropFirst() works but then I get the initial duplicate edge case).

How can I setup the sink up so that it only triggers if myState actually changes (toggles) and also not get the initial sink at setup?

CodePudding user response:

Use .scan to pair the currently propagating value with the previously propagated value (as a tuple). You can then, in a subsequent operator, decide how to handle the tuple, letting the value proceed down the pipeline only if it consists of two different values.

CodePudding user response:

If I understand you correctly, you expect the first value to make it sink to be true. I that is the case you simply have to swap dropFirst() and removeDuplicates() around:

 model.$myState
    .removeDuplicates()
    .dropFirst()
    .receive(on: RunLoop.main)
    .sink { [weak self] myState in
        print("myState: \(myState)")
    }
    .store(in: &subs)
  • Related