James Woodcock
James Woodcock

Reputation: 449

SwiftUI TextField doesn't commit change when tapping another TextField

I am building some basic form functionality in my app at the moment and I am having trouble with TextFields not changing the value in the relevant binded variable when tapping another TextField or pressing "Done" in Edit Mode.

    @Binding var jobDetails: JobDetails
    @Environment(\.colorScheme) var colorScheme: ColorScheme

    ...

    var body: some View {

       ...
                        HStack {
                            Text("Hourly Rate")
                            Spacer()
                            TextField("", value: $jobDetails.hourlyRateBasic, formatter: TextFormatters().currencyFormatter())

                                .keyboardType(.asciiCapableNumberPad)
                                .multilineTextAlignment(.trailing)
       ...

In the iOS simulator, the field only seems to update when I physically hit the return key on my keyboard after typing in a new value (not the soft keyboard in the simulator). I would like the TextField to commit it's change to jobDetails.hourlyRateBasic when tapping another TextField or pressing "Done" to exit edit mode.

It seems that onEditingChanged fires when I tap another TextField, but I don't know how to leverage that into changing the jobDetails with the new value.

Upvotes: 14

Views: 3694

Answers (2)

Asperi
Asperi

Reputation: 258345

This is already fixed. Tested with Xcode 13.3 / iOS 15.4

demo

struct TestView: View {
    @State private var value1 = 1.0
    @State private var text = ""

    private var currencyFormatter: NumberFormatter = {
         var nf = NumberFormatter()
         nf.numberStyle = .currency
         return nf
    }()

    var body: some View {
        VStack {
            HStack {
                Text("Hourly Rate [\(value1)]")
                Spacer()
                TextField("", value: $value1, formatter: currencyFormatter)

                    .keyboardType(.asciiCapableNumberPad)
                    .multilineTextAlignment(.trailing)
            }
            HStack {
                Text("Other")
                Spacer()
                TextField("Enter something", text: $text)
            }
        }
    }
}

Upvotes: 0

NikzJon
NikzJon

Reputation: 954

This is typical behavior of TextField in SwiftUI. Following is an example of it and alternative method to make TextField more responsive while typing.

import SwiftUI

struct ContentView: View {
    @State private var text: String = "0"
    @State private var num: Int = 0
    private var resultString: String {
        if let num = Int(self.text) {
            return String(num*num)
        }
        return "0"
    }
    private var resultInt: Int {
        return self.num*self.num
    }
    var body: some View {
        VStack {
            VStack(alignment:.leading) {
                Text("Input number as String")
                TextField("String Number",text: self.$text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                Text("Input number as Int")
                TextField("Int Number", value: self.$num, formatter: NumberFormatter())
                .textFieldStyle(RoundedBorderTextFieldStyle())
            }
            Spacer()
            Text("From String")
            Text("Square of \(self.text) is \(self.resultString)") .font(.title)
            Spacer()
            Text("From Int")
            Text("Square of \(self.num) is \(self.resultInt)") .font(.title)
            Spacer()
        }.padding()
    }
}

Upvotes: 1

Related Questions