向SwiftUI Picker添加回调

sli*_*cer 6 callback picker swiftui

我正在尝试向SwiftUI选择器添加回调,但无法使其执行。当选择器值更改时,didSet显然不会执行。到目前为止,这是我尝试过的方法:

struct ContentView : View {
    @State private var picked: Int = 0 {didSet{print("here")}}
    var someData = ["a", "b", "c"]
    var body: some View {

        VStack {
            Picker(selection: $picked,
                   label: Text("")) {
                    ForEach(0 ..< someData.count)     {Text(self.someData[$0]).tag($0)}
            }
            .pickerStyle(.wheel)
            Text("you picked: \(someData[picked])")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

kon*_*iki 6

代码已更新至Beta 6

@State变量将永远不会执行didSet,因为它不会更改。改变的是包装值。因此,我认为可以利用它的唯一方法是在中间放置第二个绑定,以充当中介,并传递价值。这样,您可以在其中放置回调。

struct ContentView : View {
    @State private var picked: Int = 0

    var someData = ["a", "b", "c"]
    var body: some View {

        let p = Binding<Int>(get: {
            return self.picked
        }, set: {
            self.picked = $0

            // your callback goes here
            print("setting value \($0)")
        })


        return VStack {
            Picker(selection: p,
                   label: Text("")) {
                    ForEach(0 ..< someData.count) {
                        Text(self.someData[$0]).tag($0)
                    }
            }
            .pickerStyle(WheelPickerStyle())
            Text("you picked: \(someData[picked])")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


rra*_*ael 2

您不能在具有属性包装器didSet的变量上使用修饰符@State

包装State器告诉 SwiftUI 包装的值必须由 SwiftUI 框架本身管理。这意味着视图实际上并不包含该值,它只包含一个State(不可变的),它提供对包装值的某种引用。

实际上,您应该忘记didSetSwiftUI 内的回调View。该View协议需要一个body,它没有标记为mutating(SwiftUI 视图是struct)。所以 aView基本上是不可变的。