I'm trying to understand how to use .focusedSceneValue on macOS.
Given a very basic app which displays Thing-s, and have a menu for editing the things. When I run the app, nothing is selected at first and the menu is disabled. When selecting e.g. the Thing Alfa in the sidebar. the menu becomes enabled as expected. When I select another Thing, the menu is also updated as expected.
However, if I switch focus to another application, e.g. the Finder, and then switch back to my app, the menu is now disabled, even though a Thing is selected in the sidebar.
If I open another window within my app and select e.g. Gamma in the sidebar of that window the menu is updated as expected. But, when switching back to the first window the menu is disabled, although a Thing is selected.
What am I doing wrong? Xcode 13.1 and macOS Monterey 12.0.1.
See the code below (the code can also be found here: https://github.com/danwaltin/FocusedSceneValueTest)
struct Thing: Identifiable, Hashable {
let id: Int
let name: String
static func things() -> [Thing] {
return [
Thing(id: 1, name: "Alfa"),
Thing(id: 2, name: "Beta"),
Thing(id: 3, name: "Gamma")
]
}
}
@main
struct FocusedSceneValueTestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
.commands {
ThingCommands()
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
List(Thing.things()) { thing in
NavigationLink(
destination: DetailView(thing: thing),
label: {Text(thing.name)}
)
}
Text("Nothing selected")
}
}
}
struct DetailView: View {
let thing: Thing
var body: some View {
Text(thing.name)
.focusedSceneValue(\.selectedThing, thing)
.navigationTitle(thing.name)
}
}
struct ThingCommands: Commands {
@FocusedValue(\.selectedThing) private var thing
var body: some Commands {
CommandMenu("Things") {
Button("Edit \(thingName)") {
print("*** Editing \(thingName)")
}
.disabled(thing == nil)
.keyboardShortcut("e")
}
}
private var thingName: String {
guard let thing = thing else {
return ""
}
return thing.name
}
}
struct SelectedThingKey : FocusedValueKey {
typealias Value = Thing
}
extension FocusedValues {
var selectedThing: Thing? {
get {self[SelectedThingKey.self]}
set {self[SelectedThingKey.self] = newValue}
}
}