OsmanBalci
OsmanBalci

Reputation: 63

SwiftUI TextField re-renders the view after each character typed. How do I make it to re-render the view only after hitting the Return key?

The same issue exists in Xcode beta 5 . Example code to illustrate the problem listed below :

struct ContentView: View {

    @State var someText = "Change me!"
    @State var someNumber = 123.0

    var body: some View {
        Form {
            // The entire View is re-rendered after each character is typed
            TextField("Text", text: $someText,
                onEditingChanged: { edit in
                    print("onEditingChanged executed!")
                },
                onCommit: {
                    print("onCommit executed!")
                }
            )

            // When you enter a Double value, the View is not re-rendered until you hit Return
            TextField("Number", value: $someNumber, formatter: NumberFormatter())
            Spacer()

            Text("text: \(self.someText), number: \(self.someNumber)")
         }
     }
}

Upvotes: 4

Views: 2222

Answers (1)

kylehug
kylehug

Reputation: 46

SwiftUI Views will be recreated each time any of their @ObservedObjects change or any time their @State changes.

You are passing a two-way binding of the View's @State to the TextField. The TextField updates the value of this two-way binding each time its input value changes. This will update the @State of the View and thus the View will be recreated.


I don't think you need to avoid recreating the View to get the effect you want. Recreating Views is the backbone of SwiftUI.

You can add an additional @State property, maybe presentedText, which you update to the value of someText inside of onEditingChanged.

For example (only changed for "text"):

struct ContentView: View {

    @State var someText = "Change me!"
    @State var someNumber = 123.0
    @State var presentedText = someText

    var body: some View {
        Form {
            // The entire View is re-rendered after each character is typed
            TextField("Text", text: $someText,
                onEditingChanged: { edit in
                    print("onEditingChanged executed!")
                    self.presentedText = someText
                },
                onCommit: {
                    print("onCommit executed!")
                }
            )

            // When you enter a Double value, the View is not re-rendered until you hit Return
            TextField("Number", value: $someNumber, formatter: NumberFormatter())
            Spacer()

            Text("text: \(self.presentedText), number: \(self.someNumber)")
         }
     }
}

Upvotes: 1

Related Questions