In SwiftUI how to to alternate between 2 menu items, when holding down the Options key
like when you open a Finder File menu and press down the Options key, some items alternate
sadly my approach still shows both options
Button("Alternative option") {
}
.keyboardShortcut(KeyEquivalent("i"), modifiers: [.command, .option])
Button("Regular option") {
}
.keyboardShortcut(KeyEquivalent("i"), modifiers: [.command])
UPDATE
I just found this modifierkeyalternate
might be just what you're looking for take a look at the Apple sample code.
// File
// Save
Button("Save", ...) // ⌘ S
.keyboardShortcut("s")
.modifierKeyAlternate(.option) {
Button("Save All", ...) // ⌥⌘ S
}
This is because you are providing two views. You need to use an if statement to decide which one you want to display.
here is an example from one of my apps where I alter menu buttons on changes to the logged in user
import SwiftUI
struct LoginCommandsView: View {
@Environment(\.openWindow) private var openWindow
@Environment(\.dismiss) private var dismiss
@State private var loginText: String = "Login as User"
@State private var userIsAdmin: Bool = false
@State private var userIsLoggedIn: Bool = false
var body: some View {
//FIXME: - see bug notes
loginButton
.onAppear {
setParameters(Company.shared.currentUser)
}
//bug fix on change not always called
.onReceive(NotificationCenter.default.publisher(for: .authenticationState), perform: { _ in
setParameters(Company.shared.currentUser)
})
//bug fix on receive not always called
.onChange(of: Company.shared.currentUser) { _, newValue in
setParameters(newValue)
}
if userIsLoggedIn {
changePassword
}
if userIsAdmin {
createUser
}
if userIsLoggedIn {
logoutButton
}
}
@ViewBuilder
private var loginButton: some View {
Button(loginText) {
Company.shared.currentUser = nil
CompanyData.shared.save()
openWindow(id: WindowConstants.loginView)
}
}
private var changePassword: some View {
Button("Change Password") {
openWindow(id: WindowConstants.changePassword)
}
}
private var createUser: some View {
Button("Create New User") {
openWindow(id: WindowConstants.userCreate)
}
}
private var logoutButton: some View {
Button("Logout") {
logout()
}
}
private func logout() {
Company.shared.currentUser = nil
CompanyData.shared.save()
openWindow(id: WindowConstants.loginView)
dismiss()
}
private func setParameters(_ user: User?) {
if user == nil {
loginText = "Login"
userIsAdmin = false
userIsLoggedIn = false
} else {
userIsLoggedIn = true
loginText = "Switch User"
userIsAdmin = user!.userIsAdmin
}
}
}
in your case you could just do
if someCondition {
Button("Alternative option") {
}
.keyboardShortcut(KeyEquivalent("i"), modifiers: [.command, .option])
} else {
Button("Regular option") {
}
.keyboardShortcut(KeyEquivalent("i"), modifiers: [.command])
}
note that this view is utilized in .commands
of the window group to which it applies "in my case all of them"
.commands {
//MARK: - commands
Group {
//MARK: New Item Commands
CommandGroup(replacing: .newItem) {
LoginCommandsView()
.onReceive(NotificationCenter.default.publisher(for: .authenticationState)) { _ in
showFullMenu = Company.shared.currentUser != nil
}
}
}
and that show full menu just adds the other menu items available if the user is authenticated. from inside the .commands closure.