While working on a new feature for my SimRecorder app, I found an interesting issue with SwiftUI Picker that I want to share with you.
The problem
I want to display a SwiftUI View, containing a Picker, so that users can choose a Simulator from the list of booted Simulators to work with. The ID of the selected simulator is stored in the selectedSimulator
variable which has the type Simulator
struct SimulatorSettingsSideBarView: View {
@ObservedObject var controller: SimulatorsController
@State private var selectedSimulator: Simulator?
var body: some View {
VStack(alignment: .leading) {
List {
Section("Simulators") {
Picker(
"",
selection: $selectedSimulator
) {
ForEach(controller.bootedSimulators, id: \.self) {
Text($0.name)
.tag($0)
}
}
.labelsHidden()
}
}
Spacer()
}
}
}
The problem is that, when I run the above code, the Picker
will not persist my selection. As you can see in the video, the Picker
reset itself to the not-selected state whenever users choose a simulator.
The Solution
After reading the Picker’s Apple Documentation carefully again, I found this important sentence
Use an optional value for the selection input parameter. For that to work, you need to explicitly cast the tag modifier’s input as Optional to match. For an example of this, see
tag(_:)
.
As the selectedSimulator
has the type of Simulator?
to indicate a not-selected state when its value equals nil
. The doc indicates that we need to do something else to make Picker
work properly.
Following the link to the tag(_:)
method documentation, I can see this important sentence
The Picker requires the tags to have a type that exactly matches the selection type, which in this case is an optional Flavor
From there, I can easily fix my issue by casting the parameters in the tag
method to the same optional Simulator
type to match the type of selectedSimulator
variable
struct SimulatorSettingsSideBarView: View {
....
var body: some View {
.....
Text($0.name)
.tag($0 as Simulator?)
.....
}
}
Now, everything is working as expected
Conclusion
Hopefully, this short post will save you some time when investigating why your Picker View doesn’t work. The learning here can be compressed in this important sentence from the Apple Documentation
The
Picker
requires the tags to have a type that exactly matches the selection type