top-level menu visibility in swiftui for macos_南国之风的博客-爱代码爱编程
Posted 1 year ago by Peter Steinberger
Pretty much all Mac apps have a semi-hidden Debug menu that can be triggered via a user defaults entry or via settings. Naturally I wanted to add the same in my latest project. I’m building a new “universal” app (meaning iOS and macOS), supporting only the latest OSes, so I can using the new SwiftUI app lifecycle.
SwiftUI is really a lot of fun to work with. Sure, there are bugs, warts and parts that simply aren’t finished yet, especially on the Mac, but overall what Apple built here is really great, and it’s so much faster to build apps with it. SwiftUI makes the hard things simple, and sometimes it makes the simple things hard.
Menus in SwiftUI App Lifecycle
Let’s look at a typical menu definition in the new Big Sur/iOS 14 SwiftUI App Lifecycle. The syntax is straightforward and fits right into the concepts of SwiftUI. Bingings work as well and menus change on-demand as state changes.
There’s a superb guide over at TrozWare about SwifUI Mac Menus that explains everything in detail - including a way how to move the menu logic into a separate file. Highly recommended. Let’s move on to the interesting bits.
Showing Menus Conditionally
CommandMenu it’s easy to use
else to conditionally show menu entries. SwiftUI uses
@ViewBuilder as resultbuilder and conditionals are correctly implemented.
However if we try the same at the top level, we get an error:
"Closure containing control flow statement cannot be used with result builder 'CommandsBuilder'"gs. The SwiftUI-team didn’t implement any branching logic into the
Make sure to trigger this both on app start and whenever the debug value changes:
And that’s it. Toggling the menu works just as expected. In our update method we have to skip a runloop so the SwiftUI glue has time to set up the menu, however this gets called so early in the app startup lifecycle that it’s not visible. So while not the most elegant solution, this works perfectly fine.
This is a good reminder that even when writing a “Pure SwiftUI” application, the underlying frameworks are there and can help you whenever you run into a limitation of SwiftUI. Since this feels like an omission, I’ve opened a radar (FB9074334) for the SwiftUI team.