1
\$\begingroup\$

I'm creating a Settings-form in SwiftUI. One of the expected values is a double.

I tinkered with NumberFormatter, but it didn't work well for me.

Moreover I had to find a way making invalid values visible to the user.

Correct    Invalid

Here's the solution, which I have developed. Please pay attention to the comments I have put in the code.

struct SettingsView: View {
    @Binding var isSettingsShown: Bool
    @Binding var step: Double // Actual value is a Double.
    @Binding var unit: String
    
    @State private var strStep = "" // Binding-value becomes declared as String.
    @State private var isFormInvalid = true
    
    var body: some View {
        NavigationStack {
            Form {
                Section("Unit of measurement") {
                    TextField("Gram, liter, Car, Pedestrian ...", text: $unit)
                }
                Section("Step length") {
                    TextField("1, 5, 31.1, 0.75 ...", text: $strStep)
                        .keyboardType(.decimalPad)
                        .font(.title)
                }
                if isFormInvalid == true { // Handling an in-/valid form.
                    Section("Invalid data") {
                        Text("Step length")
                            .frame(alignment: .center)
                            .foregroundStyle(.red)
                            .bold()
                    }
                } else {
                    Section {
                        Button {
                            isSettingsShown.toggle()
                        } label: {
                            Text("Submit")
                                .padding()
                                .frame(height: 40)
                                .frame(maxWidth: .infinity)
                                .background(.blue)
                                .foregroundStyle(.white)
                                .bold()
                                .clipShape(RoundedRectangle(cornerRadius: 12))
                        }
                    }
                }
            }.toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button("Close", systemImage: "xmark.circle") {
                        isSettingsShown.toggle()
                    }
                }
            }.navigationTitle("Settings")
        }.onAppear() {
            UITextField.appearance().clearButtonMode = .whileEditing
            strStep = "\(step)"
        }.onChange(of: strStep) {
            strStep = strStep.replacingOccurrences(of: ",", with: ".")
            if let dblStep =  Double(strStep) { // If the temporary String-value can become casted to a double ...
                isFormInvalid = false
                step = dblStep // ... the actual value becomes set to the casted value.
            } else {
                isFormInvalid = true // Otherwise the form becomes declared as invalid.
            }
        }
    }
}

Is the requirement fulfilled in a good way, or are there weak points which have to be improved?

Should I choose a completely different approach?

\$\endgroup\$

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.