I'm trying to add a submenu off one of my menu items using the following code:
import SwiftUI
@main
struct MenuAppApp: App
{
var body: some Scene
{
WindowGroup
{
ContentView()
}
.commands
{
MyMenu()
}
}
}
struct MyMenu: Commands
{
let array = ["Submenu 1", "Submenu 2", "Submenu 3"]
@State var selected = "Submenu 1"
var body: some Commands
{
CommandMenu("My Menu")
{
Button("First Thing")
{
print ("First Thing")
}
Divider()
Picker(selection: $selected, label: Text("Second Thing"))
{
ForEach (Array(array.enumerated()), id: \.element)
{ index, item in
Text(item).tag(item)
// Button(item)
// {
// print("Button \(item) selected")
// }
}
}
.onChange(of: selected)
{
print ("OnChange \(selected)")
}
}
}
}
struct ContentView: View
{
var body: some View
{
VStack
{
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
}
}
This renders the menu correctly but it will not execute the onChange portion of the menu until after the second time of choosing the menu.
Select Second Thing → Submenu 2 Nothing happens Click once anywhere on the menu bar It will then print "On Change Submenu 2"
You have to reselect any menu in the menu bar before the action will be executed.
If I uncomment the button code then button action never gets executed.
I also tried moving the selected State var to the top level and then using a binding. This did exactly the same.
How should I do this properly?
A possible solution is a custom Binding between selected
and the picker
struct MyMenu: Commands
{
let array = ["Submenu 1", "Submenu 2", "Submenu 3"]
@State private var selected = "Submenu 1"
var body: some Commands
{
let secondThingBinding = Binding {
selected
} set: { newValue in
selected = newValue
print ("OnChange \(newValue)")
}
CommandMenu("My Menu")
{
Button("First Thing")
{
print ("First Thing")
}
Divider()
Picker(selection: secondThingBinding, label: Text("Second Thing"))
{
ForEach (Array(array.enumerated()), id: \.element)
{ index, item in
Text(item).tag(item)
// Button(item)
// {
// print("Button \(item) selected")
// }
}
}
}
}
}