TechnologiesSwiftUI

FocusedObject struct

iOSmacOStvOSwatchOSvisionOSiOS 16.0+✓ renders

A property wrapper type for an observable object supplied by the focused

How it works

FocusedObject is a property wrapper that reads an observable object published into the focused view hierarchy, giving you a live handle on the model that belongs to whatever is currently in focus. Reach for it when a command, toolbar, status bar, or inspector needs to act on the object behind the active editor without that object being threaded down through bindings or the environment. Because the wrapped value tracks focus, it resolves to the right instance as focus moves and becomes nil when nothing focusable is supplying one. It is the ObservableObject counterpart to FocusedValue, observing the object so your view updates whenever its published properties change.

  1. Publish the object with focusedSceneObject(_:)

    An object only becomes available to FocusedObject once a view in the hierarchy exposes it for focus. Applying .focusedSceneObject(document) to the editing view publishes that Document instance into the scene's focus context, where it can be picked up by any reader. Here the Editor view attaches it to its TextField, so the document travels with the field's focus.

  2. Declare the reader as an optional ObservableObject

    FocusedObject wraps an ObservableObject and always vends an optional, because there may be no focused object to read. @FocusedObject private var document: Document? in StatusBar matches the published Document by its type; SwiftUI fills it in with the focused instance, or leaves it nil when none is present.

  3. Read the wrapped value and observe its changes

    Accessing the property yields the focused object directly, and because FocusedObject observes it, the view re-renders when the object's @Published members change. StatusBar reads document?.title, so as the bound title is edited through the field it stays in sync, falling back to "No document" via the nil-coalescing default when nothing is focused.

  4. Keep the type the matching key

    FocusedObject identifies what to read purely by the declared object type, so the type used to publish and the type used to read must line up. The Document class — a final class conforming to ObservableObject — is the shared key between .focusedSceneObject(document) on the producing side and @FocusedObject private var document: Document? on the consuming side.

Try it — Type a new name into the TextField bound to $document.title, and watch the Label in StatusBar update its text through document?.title as focus stays on the field.

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.

FocusedObject.swift
struct FocusedObjectDemo: View {
    final class Document: ObservableObject {
        @Published var title: String = "Untitled.txt"
    }

    struct Editor: View {
        @StateObject private var document = Document()

        var body: some View {
            TextField("Title", text: $document.title)
                .textFieldStyle(.roundedBorder)
                .focusedSceneObject(document)
        }
    }

    struct StatusBar: View {
        @FocusedObject private var document: Document?

        var body: some View {
            Label(document?.title ?? "No document", systemImage: "doc.text")
                .font(.headline)
        }
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            Editor()
            Divider()
            StatusBar()
        }
        .padding()
    }
}
Live preview
9:41
9:41
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →