14

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.

7
  • ‘JobDetails’ is a struct so I don’t believe I can do what you’re suggesting. The type of .hourlyRateBasic is Double? as I’ve seen is required in some other resources. The updating of jobDetails works perfectly when pressing enter on the TextField after editing, which is why I am confused as to it not updating. jobDetails has another property that is a String and the updating works fine for this property. I will edit my answer in the morning to include more code. Thanks for your help. Commented Aug 7, 2019 at 21:38
  • 4
    I have seen this too and I think the root issue is that for TextFields that supply a formatter, the formatter is only getting called when return is hit. If no formatter is supplied, the TextField's value is updated with each keypress. And since the value is not updated, I don't see any way of getting the user's input even in onEditingChanged. Once again, it's a SwiftUI bug we have to hope will be fixed soon. Commented Aug 8, 2019 at 0:24
  • 1
    @KRH is right about the formatter. It seems to me that it is indeed a bug. I put a breakpoint in the formatter's isPartialStringValid(...) method, and it is never called. You should submit a bug report. Commented Aug 8, 2019 at 4:17
  • 1
    Thank you both, I had a feeling that this might be the case. I will file a bug report and hope it is fixed in beta 6, and add an answer when it is resolved. Commented Aug 8, 2019 at 8:08
  • 1
    Not to continue the witch hunt here. But I am having the same issue with stored Double (ie. 4.87). When I render on my phone it looks just fine. However, when I click on the text fields to edit the Double Value; the value just persists and never gets updated. Commented Sep 28, 2019 at 20:39

2 Answers 2

1

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()
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Does this actually answer the question? I can’t see how this helps in committing the change on the number field.
0

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)
            }
        }
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.