Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

How to use `.focusedSceneObject()` with @Observable?

According to docs, .focusedObject() usage should be moved to .focusedValue() when migrating to @Observable, but there is no .focusedSceneValue() overload that accepts Observable like with .focusedValue(). So how are we supposed migrate .focusedSceneObject() to @Observable?

The migration from .focusedSceneObject() to @Observable in SwiftUI can be achieved by using a @State property to store the focused value and then binding the focused property of the view to this @State property. Here's how you can migrate from .focusedSceneObject() to @Observable:

  1. Define an @Observable Property:

    Create an @Observable property that will store the focused value. This property can be of any appropriate data type, such as a String or a custom struct. For example:

    @Observable var focusedValue: String = ""
    
  2. Bind focused to the @Observable Property:

    Instead of using .focusedSceneObject(), you can bind the focused property of a view to your @Observable property using the $ syntax. This allows you to set and get the focused value.

    For example, if you were using .focusedSceneObject() like this:

    .focusedSceneObject(\.focusedValue)
    

    You can migrate it to @Observable like this:

    .focused($focusedValue)
    

    This binding connects the view's focus state to the focusedValue property.

  3. Update Usage of the Focused Value:

    Wherever you were using .focusedSceneObject(\.focusedValue), you can now use the focusedValue property directly.

    For example, if you had a Text view displaying the focused value:

    Text("Focused Value: \(focusedValue)")
    

    This code will still work with the focusedValue property defined in step 1.

By following these steps, you can migrate from .focusedSceneObject() to @Observable while maintaining the functionality of managing the focused value in your SwiftUI view.

I'm just migrating some ObservedObjects to Observable and ran into this problem with a Commands menu with a FocusedObject dependency. I want some entries in the menu to be enabled and to act on state from the Observable object.

What finally worked for me (so far) is using a FocusedValues extension. I couldn't get this to work without the key path API, despite what the documentation says, and there doesn't appear to be a single example on the Internet.

struct MyFocusedObservableStateValue: FocusedValueKey {
    typealias Value = MyObservableStateType
}

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

struct ItemActionsCommandMenu: Commands {
    @FocusedValue(\.myObservableState) var myObservableState

    var body: some Commands {
        CommandMenu("Menu Name") {
             // use myObservableState as needed (Note: It's optional)
             Button("Action") {
             }
             .disabled(...)
         }
    }
}

Elsewhere in App:

myContentView
  .focusedSceneValue(\.myObservableState, myObservableState)
How to use `.focusedSceneObject()` with @Observable?
 
 
Q