Using the native SwiftUI.Picker to set a @State
which is then used to render different child views based on the selected state (using a switch-case inside body) seems to cause those child views to be unresponsive.
The following code below is a replicates the issue. The solution I am currently using is to build my own custom Picker
that relies on SwiftUI.Buttons
to set the state. This works.
enum PickerSelection: Hashable {
case binding, ownState
}
struct MainApp: View {
@State private var pickerSelection: PickerSelection? = nil
@State private var isToggled: Bool = false
var body: some View {
VStack(alignment: .leading) {
/// Changing `pickerSelection` via `SwiftUI.Picker` causes child views' toggles to be unresponsive.
Picker("Picker", selection: $pickerSelection) {
Text("No Option").tag(Optional<PickerSelection>(nil))
Text("Binding").tag(PickerSelection.binding)
Text("Own state").tag(PickerSelection.ownState)
}
/// Changing `pickerSelection` via a custom `Button`-based picker works as expected.
CustomPickerWithButtonBased(pickerSelection: $pickerSelection)
switch pickerSelection {
case .binding:
ChildViewWithBinding(isToggled: $isToggled)
case .ownState:
ChildViewManagingOwnState()
case .none:
EmptyView()
}
Spacer()
}
.padding()
}
}
struct ChildViewWithBinding: View {
@Binding var isToggled: Bool
var body: some View {
Toggle("ChildViewWithBinding", isOn: $isToggled)
}
}
struct ChildViewManagingOwnState: View {
@State private var isToggled: Bool = false
var body: some View {
Toggle("ChildViewManagingOwnState", isOn: $isToggled)
}
}
struct CustomPickerWithButtonBased: View {
@Binding var pickerSelection: PickerSelection?
var body: some View {
HStack {
Button {
pickerSelection = .binding
} label: {
Text("Binding")
}
Button {
pickerSelection = .ownState
} label: {
Text("OwnState")
}
}
}
}
Am I missing something with Picker
?