I seem to be using (context) menus incorrectly in SwiftUI (or there is a serious bug):
When a menu is open and the user taps another button (⛭) in the background that is supposed to open a sheet, the menu closes automatically, but no sheet is shown.
What's worse: After that, I can tap the button as many times as I like and still nothing happens. Instead, the following warning is printed to the log (only the first time):
[Presentation] Attempt to present <TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView: 0x105818200> on <TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier_: 0x10601e000> (from <TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier_: 0x10601e000>) which is already presenting <_UIContextMenuActionsOnlyViewController: 0x107308e30>.
Apparently, SwiftUI presents the menu as a modal view under the hood and the settings view as well, but UIKit cannot present two modals at the same time. While I understand this problem, I'm not certain how to solve it:
One way would be to disable entirely disable user-interaction on the background (i.e. on everything that's not part of the menu). But I haven't been able to find a reliable way to do that or to even detect when the menu is open. This is the best attempt of a solution I've found. Is there a better one?
Another way would be to somehow first dismiss the menu before the sheet is opened. But again, I don't know how to do this. Any ideas?
This is a minimal code example to replicate the behavior:
struct ContentView: View {
@State private var displaySettings: Bool = false
var body: some View {
Button {
displaySettings = true
} label: {
Image(systemName: "gearshape.fill")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50)
}
.toolbar {
ToolbarItem(placement: .bottomBar) {
Menu {
Button(action: {}) {
Label("Reset", systemImage: "arrow.counterclockwise")
}
} label: {
Image(systemName: "ellipsis.circle")
}
}
}
.sheet(isPresented: $displaySettings) {
Text("Settings")
}
}
}
⚠️ Please note that the problem only occurs on real devices. The simulator doesn't have this problem and shows the sheet as intended.