Skip to content

FocusedValue and FocusedBinding (SwiftUI)

A SwiftUI guide for coding agents. Also covers focusedvalue, focusedvaluekey, read focused view content, focusedbinding, menu act on focused editor, focusedsceneValue.

@FocusedValue reads a value published by whichever view currently has focus, the way @Environment reads shared values. The classic use is a macOS main-menu command that acts on the focused editor's content.

Publishing a Focused Value

Define a FocusedValueKey and register it on FocusedValues. The property must be optional: SwiftUI sets it to nil when no matching view has focus.

struct FocusedNoteValue: FocusedValueKey {
  typealias Value = String
}

extension FocusedValues {
  var noteValue: FocusedNoteValue.Value? {
    get { self[FocusedNoteValue.self] }
    set { self[FocusedNoteValue.self] = newValue }
  }
}

The focused view publishes with the focusedValue modifier, and any other view observes it.

struct NoteEditor: View {
  @State private var note = "text"

  var body: some View {
    TextEditor(text: $note)
      .focusedValue(\.noteValue, note)
  }
}

struct NotePreview: View {
  @FocusedValue(\.noteValue) var note

  var body: some View {
    Text(note ?? "Note is not focused")
  }
}

Use focusedSceneValue instead when the reader lives in a different scene, such as a menu command. For an ObservableObject rather than a value, the pair is focusedObject and @FocusedObject (scene variant focusedSceneObject).

Writing Back With FocusedBinding

@FocusedValue is read-only. To mutate the focused content, publish a Binding as the focused value and read it with @FocusedBinding.

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

// NoteEditor publishes the binding:
TextEditor(text: $note)
  .focusedValue(\.noteBinding, $note)

struct NoteFormatter: View {
  @FocusedBinding(\.noteBinding) var note

  var body: some View {
    VStack {
      Text(note ?? "Note is not focused")
      Button("Clear note") { note = "" }
    }
  }
}

Assigning through the wrapper writes straight into the focused editor's state. Everything here goes nil the moment focus leaves, so always handle the unfocused case.

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-swiftui-guide({ topic: "swiftui-focusedvalue-and-focusedbinding-property-wrappers" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems
FocusedValue and FocusedBinding (SwiftUI): SwiftUI guide for coding agents | Better Design