I have just started learning SwiftUI and got stuck somewhere!
I am trying to change segment styled picker datasource when changing value of another segment. But somehow it is not working as expected! Or else I might have coded something wrong. Can anyone figure it out please?
Here is my piece of code:
import SwiftUI
struct ContentView: View {
@State var selectedType = 0
@State var inputUnit = 0
@State var outputUnit = 1
let arrTypes = ["Temperature", "Length"]
var arrData: [String] {
switch self.selectedType {
case 0:
return ["Celsius", "Fahrenheit", "Kelvin"] //Temperature
case 1:
return ["meters", "kilometers", "feet", "yards", "miles"] //Length
default:
return ["Celsius", "Fahrenheit", "Kelvin"]
}
}
var body: some View {
NavigationView{
Form
{
Section(header: Text("Choose type"))
{
Picker("Convert", selection: $selectedType) {
ForEach(0 ..< 2, id: \.self)
{ i in
Text(self.arrTypes[i])
}
}
.pickerStyle(SegmentedPickerStyle())
}
Section(header: Text("From"))
{
Picker("", selection: $inputUnit) {
ForEach(0 ..< arrData.count, id: \.self)
{
Text(self.arrData[$0])
}
}
.pickerStyle(SegmentedPickerStyle())
}
Section(header: Text("To"))
{
Picker("", selection: $outputUnit) {
ForEach(0 ..< arrData.count, id: \.self)
{
Text(self.arrData[$0])
}
}
.pickerStyle(SegmentedPickerStyle())
}
}
}
}
}
When I change segment from Length
back to Temperature
it merges the array somehow. I tried to debug and print the arrData
count in log, then it prints correct result but not updating the UI!
First segment selected by default:
Change segment:
Change segment back to first:
Any help or suggestion would greatly be appreciated.
Nick Polychronakis solved it in this fork: https://github.com/nickpolychronakis/100DaysOfSwiftUI/tree/master/UnitCoverter
The solution is to add .id(:identifier:) to your picker so it is unique.
Observable var:
@State var unit = 0
Main picker:
Picker("Length", selection: $unit) {
ForEach(0 ..< inputUnitTypes.count) {
Text("\(self.inputUnitTypes[$0].description)")
}
}
.pickerStyle(SegmentedPickerStyle())
One of secondary pickers which content is determined by the unit variable.
Picker("Length", selection: $inputUnit) {
ForEach(0 ..< selected.count) {
Text("\(self.selected[$0].description)")
}
}
.id(unit)