TechnologiesSwiftUI

FocusedBinding struct

iOSmacOStvOSwatchOSvisionOSiOS 14.0+✓ renders

A convenience property wrapper for observing and automatically unwrapping

How it works

A FocusedBinding is a property wrapper that reads a Binding published by whichever view currently holds focus, letting a distant view read and write that view's state without a direct reference to it. Use it when a command — a toolbar button, a menu item, a keyboard shortcut — needs to act on the data of the focused control, which may change as the user moves around the interface. Where FocusedValue gives you a read-only snapshot of focus-scoped data, FocusedBinding projects a two-way connection, so the consuming view can mutate the focused view's value. Reach for it to wire up editing commands that should always operate on "the thing the user is currently editing."

  1. Define a focused-value key whose Value is a Binding

    FocusedBinding resolves its value through a key conforming to FocusedValueKey. For a writable connection the key's Value associated type must be a Binding, as in struct NoteKey: FocusedValueKey { typealias Value = Binding<String> }. The wrapper unwraps that binding so the consumer works with the underlying element type directly.

  2. Expose the key on FocusedValues

    Add a computed property to FocusedValues so the key can be referenced as a key path. Here extension FocusedValues declares var noteKey: Binding<String>? with a getter and setter that subscript into the environment via self[NoteKey.self]. The optional type reflects that no focused view may be publishing a value at a given moment.

  3. Publish the binding from the focused view

    The view that owns the data advertises its Binding for the current focus scope using the focusedValue(_:_:) modifier. In the example the TextField calls .focusedValue(\.noteKey, $note), projecting $note under the noteKey key path so any focus-aware consumer can find it while the field is focused.

  4. Read the binding with @FocusedBinding

    A separate view declares @FocusedBinding(\.noteKey) var note: String? to receive the published binding by key path. The wrapper hands back an optional of the bound element — String? rather than Binding<String> — and assigning through it, as in note = "", writes straight back to the focused view's underlying note state.

  5. Treat nil as "no focus" and gate commands

    When no view is publishing the key — nothing is focused — the projected value is nil. Use that to enable or disable the command: the EditorToolbar's Button("Clear") applies .disabled(note == nil) so it only acts when a focused field is actually supplying a binding to clear.

Try it — Click into the text field and watch the Button("Clear") enable, then comment out the .focusedValue(\.noteKey, $note) line on the TextField so the binding is never published and the button stays disabled because note is always nil.

Example & preview

Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.

FocusedBinding.swift
struct FocusedBindingDemo: View {
    @State private var note = "Hello"

    var body: some View {
        VStack(spacing: 16) {
            TextField("Note", text: $note)
                .textFieldStyle(.roundedBorder)
                .focusedValue(\.noteKey, $note)
            EditorToolbar()
            Text("You typed: \(note)")
        }
        .padding()
    }
}

struct EditorToolbar: View {
    @FocusedBinding(\.noteKey) var note: String?

    var body: some View {
        Button("Clear") { note = "" }
            .disabled(note == nil)
    }
}

struct NoteKey: FocusedValueKey {
    typealias Value = Binding<String>
}

extension FocusedValues {
    var noteKey: Binding<String>? {
        get { self[NoteKey.self] }
        set { self[NoteKey.self] = newValue }
    }
}
Live preview
Hello You typed: Hello
Hello You typed: Hello
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →