Search code examples
bindingswiftuipicker

How do I resolve Picker selection via Proxy?


Scenario: I want to handle the selection event whilst harvesting the selected item via a Picker.
This is in reference to an introduction discussion to the Picker Proxy.

This is what I have so far. I can't get the event handler to fire/activate/run doSomething().

import SwiftUI

struct ContentView: View {
    var body: some View {
        GeometryReader { _ in
            VStack {
                Text("PickerView")
                    .font(.headline)
                    .foregroundColor(.gray)
                    .padding(.top, 10)

                Picker("test", selection: Binding(get: { "" }, set: { _ in

                    doSomething()

                })) {
                    Text("Hello").id("1")
                    Text("Uncle").id("2")
                    Text("Ric").id("3")
                }.labelsHidden()

            }.background(RoundedRectangle(cornerRadius: 10)
                .foregroundColor(Color.white).shadow(radius: 1))
        }
        .padding()
    }

    func doSomething() {
        print("Hello Something!")
    }
}

Note: I don't know what to do with the get{} so I put a null string there to satisfy the compiler.

I tried evaluating the closure parameter (via print(*closure parameter*)) but got no value, so I placed a _ placeholder to satisfy the compiler.

How to I harvest the selection?

The closure parameter doesn't appear to work here; hence the placeholder. There aren't many examples to follow.


Solution

  • Here is a possible solution:

    struct ContentView: View {
        // extract picker values for easier access
        private let items = ["Hello", "Uncle", "Ric"]
    
        // store the currently selected value
        @State private var selection = 0
    
        // custom binding for the `selection`
        var binding: Binding<Int> {
            .init(get: {
                selection
            }, set: {
                selection = $0
                doSomething() // call another function after the `selection` is set
            })
        }
    
        var body: some View {
            Picker("test", selection: binding) {
                ForEach(0 ..< items.count) { index in // use `ForEach` to quickly generate picker values
                    Text(items[index])
                        .tag(index) // use `tag` instead of `id`
                }
            }
            .labelsHidden()
        }
    
        func doSomething() {
            print("Hello Something!")
        }
    }