Eric
Eric

Reputation: 672

Swiftui Textfield not updating when value changes

I have a textfield on a form where user can type value, but I would also like to update the content of the textfield with a button.

Here is my code :

struct test: View {
@State private var amount: Double = 0.0

var body: some View {
    Form {
        VStack {
            HStack {
                Text("Amount EUR")
                Spacer()
                TextField("Type amount", value: $amount, format: .number)
                    .keyboardType(.numberPad)
                    .multilineTextAlignment(.trailing)
            }
            
            Text("Set MAX (999)")
                .frame(maxWidth: .infinity, alignment: .leading)
                .onTapGesture {
                    print("before tap \(amount )")
                    amount = 999
                    print("after tap \(amount)")
                }
            
        }
    }
}

When I just launch the app, the first tap on the Text updates the textfield with 999, but after it does not work anymore. The amount value is correctly updated but the textfield does not reflect the change.

Would you have an explanation ?

Upvotes: 4

Views: 6517

Answers (1)

Yrb
Yrb

Reputation: 9725

The answer is simply that TextFields don't update while they are in focus. To solve this problem, you need to incorporate a @FocusState in to the view, and cause the TextField to lose focus right before updating the variable. You can test it in your own view by tapping your Text prior to tapping in to the TextField. You will see it updates just fine.

struct ButtonUpdateTextField: View {
    @State private var amount: Double = 0.0
    @FocusState var isFocused: Bool // <-- add here
    
    var body: some View {
        Form {
            VStack {
                HStack {
                    Text("Amount EUR")
                    Spacer()
                    TextField("Type amount", value: $amount, format: .number)
                        .keyboardType(.numberPad)
                        .multilineTextAlignment(.trailing)
                        .focused($isFocused) // <-- add here
                }
                
                Text("Set MAX (999)")
                    .frame(maxWidth: .infinity, alignment: .leading)
                    .onTapGesture {
                        print("before tap \(amount )")
                        isFocused = false // <-- add here
                        amount = 999
                        print("after tap \(amount)")
                    }
                
            }
        }
    }
}

Upvotes: 9

Related Questions