It's useful to provide code snippet that would need minimum interaction to reproduce the problem. In this case, the ContentView body
struct ContentView: View {
@State var showActionSheet = false
var body: some View {
NavigationView {
Button(action: { self.showActionSheet = true }) {
Text("Click")
}
.actionSheet(isPresented: $showActionSheet) {
ActionSheet(title: Text("This should be presented once (Button)"))
}
.navigationBarTitle("Title")
.navigationBarItems(trailing: Button(action: { self.showActionSheet = true }) {
Text("Show")
}.actionSheet(isPresented: $showActionSheet) {
ActionSheet(title: Text("This should be presented once (Navigation View)"))
})
}
}
}
I couldn't reproduce the problem in actual iOS (I don't have Catalina), so it could be Previewbug. In fact, when there is a runtime warning
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
SingleViewTest[] Warning: Attempt to present <UIAlertController> on <UINavigationController> which is already presenting (null)
Which could be the cause, that Preview doesn't know how to respond to this.
Let me explain:
You tried to present the actionSheet twice, once from view Button, and again from navigation bar Button.
When you click either button, showActionSheet will become true, and so both actionSheets will try to present themselves, but there can be only one actionSheet presented at any time, hence the warning. You should instead put actionSheet in a single place so that when either button is clicked, only one actionSheet will be presented.
SwiftUI still has many issues with modal sheets of all kinds from within a NavigationView hierarchy. If you ensure the action that brings up the sheet and the sheet itself are outside the NavigationView hierarchy, sheets work as intended.
I just fresh install Catalina with Xcode 11.1 (11A1027). So I tried your code on preview and simulator, and it only appear once. Maybe it's fixed on later version of Xcode? I'm not too sure either.
Regardless Xcode version, which iOS version do you test that with? Try testing the application on a real device with the latest iOS version. Avoid iOS 13.0 because it has non obvious SwiftUI bugs.
It's going to be behave like this for two reasons:
The button that sets self.showActionSheet is in navigationBarItems. If you create a vStack and put the button and NavigationView in it, then this is the first step to circumventing the problem.
The actionSheet is in the NavigationView hiearchy. Make actionSheet part of the vStack you put the button and NavigationView in, and it will work, every time.
I was not able to dismiss a sheet until I put it outside of NavigationView. So I guess it is still an issue over a year later, with Xcode 12.5 SwiftUI.