I am new to swift so I apologize for my ignorance but here is my issue please correct me if I have anything wrong. I am learning.
I have three pickers that in a hierarchy. Picker 1 (War Period), Picker 2’s options (Nation) depend on Picker 1’s selection, and Picker 3’s options (Force Diagram) depend on Picker 2’s selection.
When I select the pickers in order the selections are displayed properly. However, if I were to go back and change picker 1’s selection, picker 2s options get changed but not picker 3. If I change picker 2’s selection, picker 3 updates properly. How do I update all the selections to show properly when any picker is changed? See the below code.
import SwiftUI
struct Testing_View: View {
@State private var warPeriods = ""
@State private var selectedNation = ""
@State private var forceDiagram = ""
// Select war periods
let periods = ["Early War", "Mid-War", "Late War"]
// Select Nation options
let nations: [String: [String]] = [
"Early War": ["Early American", "Early Axis-Allies", "Early British", "Early German", "Early Soviet"],
"Mid-War": ["Eastern Front", "North Africa"],
"Late War": ["American", "Axis-Allies", "British", "German", "Soviet"]
]
// Select Force Diagram options
let diagrams: [String: [String]] = [
"Early American" : ["E-Day: American", "EBulge: American"],
"Early Axis-Allies" : ["EBagration: Axis-Allies"],
"Early British": ["ED-Day: British", "EBulge: British"],
"Early German": ["ED-Day: German", "ED-Day: Waffen-SS", "EBagration: German", "EBulge: German", "EBerlin: German"],
"Early Soviet": ["EBagration: Soviet", "EBerlin: Soviet"],
"Eastern Front" : ["German: Ghost Panzers", "German: Iron Cross", "Soviet: Enemy at the Gate", "Soviet: Red Banner"],
"North Africa" : ["British: Armoured Fist", "German: Afrika Korps", "Italian: Avanti", "American: Fighting First"],
"American" : ["D-Day: American", "Bulge: American"],
"Axis-Allies" : ["Bagration: Axis-Allies"],
"British": ["D-Day: British", "Bulge: British"],
"German": ["D-Day: German", "D-Day: Waffen-SS", "Bagration: German", "Bulge: German", "Berlin: German"],
"Soviet": ["Bagration: Soviet", "Berlin: Soviet"]
]
var body: some View {
NavigationView {
Form {
Picker("Select War Period:", selection: $warPeriods) {
ForEach(periods, id: .self) {
Text($0)
}
}
//.pickerStyle(.segmented)
Picker("Select Nation:", selection: $selectedNation) {
ForEach(nations[warPeriods] ?? [], id: .self) { subOption in
Text(subOption)
}
}
Picker("Select Force Diagram:", selection: $forceDiagram) {
ForEach(diagrams[selectedNation] ?? [], id: .self) { subSubOption in
Text(subSubOption)
}
}
}
}
}
}
#Preview {
Testing_View()
}
I have tried making separate arrays for each option and using if else statements for the pickers to manually do this but the results were the same.
2
Answers
First I would add two array properties instead of using the dictionaries
Then you also need to fix the Picker components so that each item gets a
tag
for matching against the selection property and you also need a choice for nothing selected ("")The same change is needed for all pickers.
Then I would use the
onChange
modifier to keep the next selection and array properties up to date when a previous selection changes.The whole
Form
partPlease excuse my English.
The reason is when you change first picker selection, the selected values of second and third pickers aren’t changed. As the picker2 is shown based the selection of picker1, so picker2’s options are changed. But as picker2’s selected value isn’t changed, so picker3’s options aren’t changed.
Set default selection value when parent picker’s selection updated.