How do I get notified (e.g., launch a function) when a Picker is used?

Scenario:

User selects a static item from a Picker which is stored into a $State variable.


Desired feature:

A function (e.g. doSomething( ) ) is fired EVERY TIME the Picker is used or whenever the $State variable has changed.


@State private var currentChoice = 0 {
        didSet {
           doSomething()
        }
    }
...
 Picker("Weapon", selection: $currentChoice) {
       ForEach(0 ..< moves.count) {
            Text("\(self.moves[$0])")
      }
 }.pickerStyle(SegmentedPickerStyle())



Question: What's the correct declarative/SwiftUI/Combine paradigm to use?

Do I have to make Picker a publisher?

How is that done in this particular scenario?

Replies

I'm guessing the didSet() doesn't work? Hm, I thought that should work as-is.


The alternative is to tie it into a publisher somehow. You can use a CurrentValueSubject<MyChoiceType, Never> to feed into your state, though, allowing you to attach other actions:


private var subscribers: Set = []
private var subject = CurrentValueSubject<int, never="">()
private var currentChoiceBinding = Binding(get: { self.subject.value }, set: { self.subject.send(newValue) })

init() {
    // assign state when the publisher gets a value
    subject.sink { self.currentChoice = $0 }
        .store(in: &subscribers)
    // call special method when the publisher gets a value
    subject.sink { doSomething() }
        .store(in: &subscribers)
}

var body: some View {
    Picker("Weapon", selection: currentChoiceBinding) {
        ForEach(0 ..< moves.count) {
            Text("\(self.moves[$0])")
        }
    }
}

The custom binding there uses the publisher's send() method to set new values, and its get() will return the current value from the publisher. Thus anything subscribed to the CurrentValueSubject will receive every value sent to the binding.

As you can see, I'm in the transition to event-handling to declarative logic.

Thanks for the suggestion... I'll pursue it.