I'm trying to add a callback to a SwiftUI picker but can't get it to execute. The didSet apparently does not execute when picker value changes. Here's what I've tried so far:
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])")
}
}
}
Code updated to beta 6
The @State variable will never execute didSet, because it does not change. What does change is the wrapped value. So the only way I can think to tap it, is by putting a second binding in the middle, to serve as an intermediary, and pass the value along. This way, you can put your callback there.
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])")
}
}
}
you can use ObservableObject to workaround it
import SwiftUI
class PickerModel:ObservableObject{
@Published var picked: Int = 0 {didSet{print("here")}}
}
struct Picker_Callback: View {
@ObservedObject var pickerModal = PickerModel()
var someData = ["a", "b", "c"]
var body: some View {
VStack {
Picker(selection: self.$pickerModal.picked,
label: Text("")) {
ForEach(0 ..< someData.count) {Text(self.someData[$0]).tag($0)}
}
//.pickerStyle(.wheel)
Text("you picked: \(someData[self.pickerModal.picked])")
}
}
}
You can't use the didSet
modifier on a variable with the @State
property wrapper.
The State
wrapper tells SwiftUI that the wrapped value must be managed by the SwiftUI framework itself. This means that the view doesn't actually contains the value, it only contains a State
(which is immutable) that provide some kind of reference to the wrapped value.
Actually, you should forget about the didSet
callback inside a SwiftUI View
.
The View
protocol requires a body
, which is not marked as mutating
(SwiftUI views are struct
). So a View
is basically immutable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With