Ryba
Ryba

Reputation: 133

Why doesn't value of SwiftUI's @FocusState property change immediately after being set?

I've noticed that when I set the value of @FocusState property, it doesn't change immediately. I found it by mistake, debugging another issue, but I would like to know why it happens.

@State properties, on the other hand, get changed right away after being set.

struct FocusStateTest: View {
    
    @FocusState private var isFocused: Bool
    @State private var text: String = ""
    
    var body: some View {
        Form {
            TextField("Tap here first", text: $text)
                .focused($isFocused)
            Text(isFocused ? "Focused" : "Blurred") // <- Works as expected
            Button("Blur") {
                print("Before:", isFocused) // <- when text field is focused, prints true
                isFocused = false
                print("After:", isFocused) // <- prints true - NOT expected
            }
        }
    }
}

Upvotes: 4

Views: 1949

Answers (1)

grandsirr
grandsirr

Reputation: 650

from Apple Docs:

When focus moves to the view, the binding sets the bound value to true. If a caller sets the value to true programmatically, then focus moves to the modified view. When focus leaves the modified view, the binding sets the value to false. If a caller sets the value to false, SwiftUI automatically dismisses focus.

This behavior happens because @FocusState is not actually a boolean value like in the @State var, but a value that tracks the current focus state in the TextField. That is, SwiftUI needs time to remove the focus on the TextField and update the FocusState. But when you trigger it immediately, TextField is still focused, thus, FocusState is true as well.

Upvotes: 4

Related Questions