@State variables seem to be getting mistakenly triggered in SwiftUI

Viewed 39

I have the following code for a simple SwiftUI project:

import SwiftUI

enum Unit: String, CaseIterable {
    case m = "Meters"
    case km = "Kilometers"
}

struct ContentView: View {
    // Note that this always has to be an int index to the array used in the picker
    @State private var inputUnit = 0
    @State private var outputUnit = 1
    @State private var inputAmount = ""
    
    let numberFormatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.alwaysShowsDecimalSeparator = false
        formatter.minimumFractionDigits = 0
        formatter.maximumFractionDigits = 2
        return formatter
    }()
    
    var inputUnitText: String {
        Unit.allCases[inputUnit].rawValue
    }
    var outputUnitText: String {
        Unit.allCases[outputUnit].rawValue
    }
    var outputAmount: Double {
        let input: Unit = Unit.allCases[inputUnit]
        let output: Unit = Unit.allCases[outputUnit]
        switch input {
        case .m:
            switch output {
            case .m: return Double(inputAmount) ?? 0
            case .km: return (Double(inputAmount) ?? 0) / 1000
            }
        case .km:
            switch output {
            case .km: return Double(inputAmount) ?? 0
            case .m: return (Double(inputAmount) ?? 0) * 1000
            }
        }
    }
    
    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Input Unit")) {
                    Picker("", selection: $inputUnit) {
                        ForEach(0..<Unit.allCases.count) {
                            Text(Unit.allCases[$0].rawValue)
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())
                }
                Section(header: Text("Input amount")) {
                    TextField(inputUnitText, text: $inputAmount)
                        .keyboardType(.numberPad)
                }
                Section(header: Text("Output Unit")) {
                    Picker("", selection: $outputUnit) {
                        ForEach(0..<Unit.allCases.count) {
                            Text(Unit.allCases[$0].rawValue)
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())
                }
                Section(header: Text("Output amount")) {
                    Text("\(numberFormatter.string(from: outputAmount as NSNumber)!) \(outputUnitText)")
                }
            }
            .navigationBarTitle("WeConvert")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

If I choose a segment on one of the segment controls or update the number the other segment controls seems to be moving. I assume their state is updating. For example:

enter image description here

If I choose an option in the second picker the first picker will also wobble like something has updated. I don't understand this because the states for both pickers are independent. Any ideas what is going on here?

0 Answers
Related