I get this error every time I launch a secondary picker.
The first picker works okay.
However when I switch pickers & scroll, I get the following:
Here is my entire code (written as a test of this problem):
import SwiftUI
struct ContentView: View {
@State private var selectedItem = 0
@State private var isMainPickerHidden = false
@State private var isSecondaryPickerHidden = true
var colors = ["Red", "Green", "Blue", "Tartan"]
var sizes = ["Tiny", "Small", "Medium", "Large", "Super Size"]
var body: some View {
ZStack {
Color.yellow.edgesIgnoringSafeArea(.all)
ZStack {
VStack {
Picker(selection: $selectedItem, label: Text("Please choose a color")) {
ForEach(colors.indices, id: \.self) {
Text(self.colors[$0])
}
}.hiddenConditionally(isHidden: isMainPickerHidden)
Text("You selected: \(colors[selectedItem])")
.hiddenConditionally(isHidden: isMainPickerHidden)
}
VStack {
Picker(selection: $selectedItem, label: Text("Please choose a size")) {
ForEach(sizes.indices, id: \.self) {
Text(self.sizes[$0])
}
}.hiddenConditionally(isHidden: isSecondaryPickerHidden)
Text("You selected: \(sizes[selectedItem])")
.hiddenConditionally(isHidden: isSecondaryPickerHidden)
Spacer()
Button(action: {
isSecondaryPickerHidden = !isSecondaryPickerHidden
isMainPickerHidden = !isMainPickerHidden
}) {
Text("Switch Pickers")
}.padding()
}
}
}
}
}
// =========================================================================================================
extension View {
func hiddenConditionally(isHidden: Bool) -> some View {
isHidden ? AnyView(hidden()) : AnyView(self)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
What is the correct syntax for the ForEach{} to avoid this problem?
This is because you use the same selectedItem
for both pickers.
If in the second picker you select the last item (index 4) and then you switch to the first picker (max index = 3), then in this line:
Text("You selected: \(colors[selectedItem])")
you'll try accessing the index which is out of range.
To fix this you can use a separate @State
variable for each picker:
struct ContentView: View {
@State private var selectedColorIndex = 0
@State private var selectedSizeIndex = 0
Picker(selection: $selectedColorIndex, label: Text("Please choose a color")) {
Picker(selection: $selectedSizeIndex, label: Text("Please choose a size")) {