1- Given a list of Sujet (Core Data managed objects for example, retrieved with @FetchRequest), in the list view :
@State private var selectedSujet: Sujet?
var body: some View {
List(selection: $selectedSujet) {
ForEach(sujets) { sujet in
NavigationLink(destination: SujetDetail(sujet: sujet)) {
SujetListItem(sujet: sujet)
}
}
}
// focused values (Object, action, Set of selection, String, Bool, ...)
// Passes the selected object in focusedSceneValue
.focusedSceneValue(\.selectedSujet, $selectedSujet)
// Passes the action to the "focus system", executed in this closure when command active in menu
.focusedSceneValue(\.deleteSujetAction) {
if let sujet = selectedSujet {
print("delete: \(sujet.name)")
}
}
}
2- Create an extension for FocusedValues for declarations
extension FocusedValues {
// Binding of optional selected object
var selectedSujet: Binding<Sujet?>? {
get { self[SelectedSujetKey.self] }
set { self[SelectedSujetKey.self] = newValue}
}
// Action declaration
var deleteSujetAction: (() -> Void)? {
get { self[DeleteSujetActionKey.self] }
set { self[DeleteSujetActionKey.self] = newValue }
}
private struct SelectedSujetKey: FocusedValueKey {
typealias Value = Binding<Sujet?>
}
private struct DeleteSujetActionKey: FocusedValueKey {
typealias Value = () -> Void
}
}
3- In MenuCommands :
struct SujetsMenuCommands: Commands {
// Retrieve the focused values
@FocusedValue(\.selectedSujet) var selectedSujet
@FocusedValue(\.deleteSujetAction) var deleteSujetAction
var body: some Commands {
CommandMenu("Sujets") {
Button { deleteSujetAction?() } label: {
Text("Delete \(selectedSujetName)")
}.disabled(selectedSujet?.wrappedValue == nil || deleteSujetAction == nil )
}
}
// private var for comfort
private var selectedSujetName: String {
if let sujet = selectedSujet?.wrappedValue {
return sujet.wrappedName
} else {
return "This Sujet"
}
}
}
If multiple selection:
// 1-
@State private var selectedDonnees = Set<Donnee.ID>()
.focusedSceneValue(\.selectedDonnees, $selectedDonnees)
// 2-
var selectedDonnees: Binding<Set<Donnee.ID>>? {
get { self[FocusedDonneesSelectionKey.self] }
set { self[FocusedDonneesSelectionKey.self] = newValue }
}
private struct FocusedDonneesSelectionKey: FocusedValueKey {
typealias Value = Binding<Set<Donnee.ID>>
}
// 3-
@FocusedBinding(\.selectedDonnees) private var selectedDonnees: Set<Donnee.ID>?
In macOS, in multi-windows app, each with its own scene, MenuCommands act accordingly with only focused scene.
I don't have tested on iPadOS.
MacOS 12 - Xcode 13 beta 5