TechnologiesSwiftUI

FocusedValue struct

iOSmacOStvOSwatchOSvisionOSiOS 14.0+✓ renders

A property wrapper for observing values from the focused view or one of its

How it works

FocusedValue is a property wrapper that reads a value published by whichever view currently holds focus. Where a regular binding ties one view to one piece of state, FocusedValue lets a distant part of the interface — a toolbar, an inspector, a menu command — observe data exposed by the focused view without that view passing a binding down through every intervening container. Reach for it when an action's meaning depends on what the user is working in right now, such as a Rename command that should operate on the note that currently has focus. The wrapper produces an optional, which becomes nil whenever nothing focused is publishing the requested value.

  1. Define a key by conforming to FocusedValueKey

    Each focused value is identified by a type that conforms to FocusedValueKey and declares the kind of data it carries through its Value associated type. In the example, SelectedNoteKey sets typealias Value = String, so this key always identifies a String flowing from the focused view to its observers.

  2. Read the value with @FocusedValue

    Apply the @FocusedValue property wrapper, passing the key type to its initializer, to subscribe to whatever the focused view currently publishes for that key. Here @FocusedValue(SelectedNoteKey.self) private var focusedNote makes focusedNote track the live value; because no focused view may be supplying it, its wrapped type is an optional String?.

  3. Publish the value with focusedValue(_:_:)

    On the producing side, the focusedValue(_:_:) view modifier attaches a value to a view under a given key, so that the value is exposed only while that view is focused. The TextField calls .focusedValue(SelectedNoteKey.self, note), advertising the current note string for the same key the reader watches.

  4. Drive it with the focus system

    FocusedValue follows SwiftUI's focus, so the published value is visible to readers only while the producing view actually holds focus. The TextField participates via .focused($isEditing), and when focus leaves it the key stops publishing and focusedNote reverts to nil.

  5. Handle the optional result

    Because the wrapped value is optional, always account for the no-focus case when you use it. The example unwraps with a default — Text("Focused note: \(focusedNote ?? "none")") — so the label reads the live note while editing and shows none once focus moves away.

Try it — Add a second TextField bound to its own @State string and give it .focusedValue(SelectedNoteKey.self, otherNote) too, then watch focusedNote switch between the two notes as you move focus between the fields.

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.

FocusedValue.swift
struct FocusedValueDemo: View {
    private struct SelectedNoteKey: FocusedValueKey {
        typealias Value = String
    }

    @State private var note = "Draft"
    @FocusState private var isEditing: Bool
    @FocusedValue(SelectedNoteKey.self) private var focusedNote

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            TextField("Note", text: $note)
                .textFieldStyle(.roundedBorder)
                .focused($isEditing)
                .focusedValue(SelectedNoteKey.self, note)

            Text("Focused note: \(focusedNote ?? "none")")
                .font(.footnote)
                .foregroundStyle(.secondary)
        }
        .padding()
    }
}
Live preview
Draft Focused note: none
Draft Focused note: none
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →