1

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.

pawello2222
  • 46,897
  • 22
  • 145
  • 209
Frederick C. Lee
  • 9,019
  • 17
  • 64
  • 105

2 Answers2

2

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!")
    }
}
pawello2222
  • 46,897
  • 22
  • 145
  • 209
1

Discussion:

You can use onChange to trigger a side effect as the result of a value changing, such as an Environment key or a Binding...

(Apple doc.)

    struct ContentView: View {
    @State
    private var selection = 0
    let items = ["Hello", "Uncle", "Ric"]
    var body: some View {
        VStack {
            Picker("", selection: $selection) {
                ForEach(0..<items.count) {
                    Text(items[$0])
                        .tag($0)
                }
            }
            .onChange(of: selection) { _ in
                print("Hello Something!")
            }
        }
    }
 }
Dim Novo
  • 367
  • 3
  • 8