Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

SwiftUI TextField not Refreshing on Variable Change

I have TextField inside a List inside a NavigationView, declared like this:

NavigationView {
    List {
        Section("Item Name") {
            TextField("", text: $itemName)
                .textInputAutocapitalization(.sentences)
                .disableAutocorrection(false)
                .textFieldStyle(.plain)
        }
    }
}

In the .onAppear method of the NavigationView, I set the textfield’s text variable, which is declared with @State, like this:

@State var itemName: String = ""

and:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

.onAppear {
    itemName = "Hello, World!"
}

The text is set properly, but the textfield somehow doesn’t refresh. I can tell because I can access the textfield’s text property and get the updated value, and when the user taps the text field to edit it, the text suddenly appears.

It seems to me to be a problem with the textfield updating its view when the variable changes. Do I have to call a SwiftUI equivalent of UIKit’s layoutSubviews? Or am I declaring my itemName variable wrong?

Minimal Reproducible Example (MRE):

struct ItemView: View {

    @State var itemName: String = ""

    var body: some View {
        NavigationView {
            List {
                Section("Item Name") {
                    TextField("", text: $itemName)
                        .textInputAutocapitalization(.sentences)
                        .disableAutocorrection(false)
                        .textFieldStyle(.plain)
                }
            }
            .navigationTitle("Item")
        }
        .onAppear {
            itemName = "Hello, World!"
        }
    }
}

Any help would be appreciated.

>Solution :

It worked fine in Preview, but I took the next step and tested it in the Simulator, and it failed. That lead me to realize what the issue was. We see this a great deal with animations that are started from .onAppear(). The view is set up and .onAppear() called before the view is actually on screen, causing a failure to update from the .onAppear(). Think of it almost as a race condition. The view has to be set up and on screen before the update can be called, and it needs an extra cycle to do this. As a result the fix is simple:

.onAppear {
    DispatchQueue.main.asyncAfter(deadline: .now()){
        itemName = "Hello, World!"
    }
}

Wrap it in a DispatchQueue.main.asyncAfter(deadline:). This gives it time to avoid the issue.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading