One Logo Pool Ball
SwiftUI · IOS API REFERENCE

FocusState

struct · iOS 15.0+ · SDK 27.1

@frozen @propertyWrapper struct FocusState<Value> where Value : Hashable

A property wrapper type that can read and write a value that SwiftUI updates as the placement of focus within the scene changes. Use this property wrapper in conjunction with ``View/focused(_:equals:)`` and ``View/focused(_:)`` to describe views whose appearance and contents relate to the location of focus in the scene. When focus enters the modified view, the wrapped value of this property updates to match a given prototype value. Similarly, when focus leaves, the wrapped value of this property resets to `nil` or `false`. Setting the property's value programmatically has the reverse effect, causing focus to move to the view associated with the updated value. In the following example of a simple login screen, when the user presses the Sign In button and one of the fields is still empty, focus moves to that field. Otherwise, the sign-in process proceeds. struct LoginForm { enum Field: Hashable { case username case password } @State private var username = "" @State private var password = "" @FocusState private var focusedField: Field? var body: some View { Form { TextField("Username", text: $username) .focused($focusedField, equals: .username) SecureField("Password", text: $password) .focused($focusedField, equals: .password) Button("Sign In") { if username.isEmpty { focusedField = .username } else if password.isEmpty { focusedField = .password } else { handleLogin(username, password) } } } } } To allow for cases where focus is completely absent from a view tree, the wrapped value must be either an optional or a Boolean. Set the focus binding to `false` or `nil` as appropriate to remove focus from all bound fields. You can also use this to remove focus from a ``TextField`` and thereby dismiss the keyboard. ### Avoid ambiguous focus bindings The same view can have multiple focus bindings. In the following example, setting `focusedField` to either `name` or `fullName` causes the field to receive focus: struct ContentView: View { enum Field: Hashable { case name case fullName } @FocusState private var focusedField: Field? var body: some View { TextField("Full Name", ...) .focused($focusedField, equals: .name) .focused($focusedField, equals: .fullName) } } On the other hand, binding the same value to two views is ambiguous. In the following example, two separate fields bind focus to the `name` value: struct ContentView: View { enum Field: Hashable { case name case fullName } @FocusState private var focusedField: Field? var body: some View { TextField("Name", ...) .focused($focusedField, equals: .name) TextField("Full Name", ...) .focused($focusedField, equals: .name) // incorrect re-use of .name } } If the user moves focus to either field, the `focusedField` binding updates to `name`. However, if the app programmatically sets the value to `name`, SwiftUI chooses the first candidate, which in this case is the "Name" field. SwiftUI also emits a runtime warning in this case, since the repeated binding is likely a programmer error. ### Nest focusable views It is important to consider the difference between ``View/focused(_:equals:)`` and ``View/focused(_:)`` with nested focusable views. For example, consider the following code: struct ContentView: View { @FocusState private var fieldIsFocused: Bool @FocusState private var containerIsFocused: Bool var body: some View { VStack { TextField("Name", ...) .focused($fieldIsFocused) } .focusable() .focused($containerIsFocused) } } The code above uses ``View/focused(_:)``, which binds focus state to the given Boolean state value. ``View/focused(_:)`` sets `containerIsFocused` to `true` both when the `VStack` itself receives focus and _just_ the `TextField` that it contains receives focus. This behavior occurs because two independent instances of `@FocusState` are used to observe the focus state of the focusable `VStack` and the `TextField`. When the `VStack` does not have focus, SwiftUI checks the view hierarchy to find the closest view with focus to set the value for `containerIsFocused`. If the `TextField` contained within this `VStack` happens to be focused, ``View/focused(_:)`` will set `containerIsFocused` to `true`. If there is need to observe whether only the `VStack` has focus, but not the inner TextField, consider using ``View/focused(_:equals:)`` instead, for more granular control. With ``View/focused(_:equals:)``, the above code can be rewritten as follows: struct ContentView: View { enum Focus { case container case field } @FocusState private var focused: Focus? var body: some View { VStack { TextField("Name", ...) .focused($focused, equals: .field) } .focusable() .focused($focused, equals: .container) } } With ``View/focused(_:equals:)``, it is possible to define a custom data structure to represent focus state. In this case, a `Focus` enumeration is used. It has two cases, one for the focusable `VStack` and another for the `TextField` it contains. ``View/focused(_:equals:)`` binds focused to `.container` only when the `VStack` itself has focus, and to `.field` when the `TextField` has focus. Because now there is only one `@FocusState` property, SwiftUI is able to disambiguate between cases when `VStack` _contains_ focus and _receives_ focus itself. Note that both of the above approaches are acceptable. ``View/focused(_:equals:)`` can be used to observe whether the given view currently receives focus. While ``View/focused(_:)`` can be used for the same purpose, additionally it can observe whether the given view contains focus.

Members (0)

This type has no directly callable members in this snapshot. See the framework’s skipped declarations for unsupported APIs.

Skipped declarations

No declarations were skipped in this snapshot.

All SwiftUI types →