I finally came to a solution. I managed to detect where the issue came from, or at least, what was causing the weird modal behaviour. To be honest, I solved the issue but I am still not understanding why this is causing such an issue. I still don't see the relationship between, and moreover, this was something not happening in iOS13, so...
In any case, let me give you two examples of the very same app, one reproducing the issue and the other one without the issue.
First let me write the MainView and the ModalView:
Code Block // a simple tabview with just one tab with a simple button opening the modal |
struct MainView: View { |
@State var showNewSuitModal = false |
|
var body: some View { |
TabView { |
Button(action: { |
self.showNewSuitModal = true |
}) { |
ZStack { |
Circle() |
.foregroundColor(Color.white) |
.frame(width: 40, height: 40) |
.shadow(radius: 5) |
.opacity(0.5) |
Image(systemName: "plus") |
.resizable() |
.frame(width: 20, height: 20) |
.foregroundColor(Color.black) |
} |
} |
.foregroundColor(Color.white) |
.padding(.bottom,20) |
.padding(.trailing,10) |
.sheet(isPresented: $showNewSuitModal) { // <-- the modal acting weird |
ModalView(isPresented: self.$showNewSuitModal) |
} |
.tabItem({ |
Image(systemName: "gauge") |
Text("Tab").fontWeight(.ultraLight) |
}) |
} |
.navigationBarBackButtonHidden(true) |
.navigationBarTitle("") |
} |
} |
|
// A simple modal with just a closing/dismissing button |
struct ModalView: View { |
@Binding var isPresented: Bool |
|
var body: some View { |
Button(action: { |
self.isPresented = false |
}) { |
ZStack { |
Circle() |
.foregroundColor(Color.white) |
.frame(width: 40, height: 40) |
.shadow(radius: 5) |
.opacity(0.5) |
Image(systemName: "minus") |
.resizable() |
.frame(width: 20, height: 20) |
.foregroundColor(Color.black) |
} |
} |
.foregroundColor(Color.white) |
.padding(.bottom,20) |
.padding(.trailing,10) |
} |
} |
And now the LaunchView, where the actual issue was detected:
Code Block |
// The launching view including just a "next" button which is linking us to |
// the MainView (the purpose of this first view is to show a disclaimer app) |
struct LaunchView: View { |
var body: some View { |
NavigationView { |
NavigationLink(destination: MainView()) { |
HStack (alignment: .center) { |
HStack { |
Image(systemName: "play") |
.font(.system(size: 16)) |
Text("Next") |
.fontWeight(.semibold) |
.font(.system(size: 16)) |
} |
.padding() |
.foregroundColor(.white) |
.background(Color.red) |
.cornerRadius(40) |
.shadow(radius: 5) |
} |
.padding() |
} |
.navigationBarTitle("Test App") |
} |
.navigationViewStyle(StackNavigationViewStyle()) |
} |
} |
This app is the one having issues, and all the issues come from the fact that the LaunchView is using a NavigationLink to jump to the next view.
Let's rewrite the app in another way so the NavigationLink is not used.
MainView and ModalView are exactly the same than in App 1.
LaunchView is as follows:
Code Block struct LaunchView: View { |
@State var disclaimerView = true |
|
var body: some View { |
NavigationView { |
VStack { |
if self.disclaimerView { |
DisclaimerView(buttonClick: $disclaimerView) |
} else { |
MainView() |
} |
} |
.navigationBarTitle("Test App") |
} |
.navigationViewStyle(StackNavigationViewStyle()) |
} |
} |
|
struct DisclaimerView: View { |
@Binding var buttonClick: Bool |
|
var body: some View { |
VStack { |
Button(action: { |
self.buttonClick.toggle() |
}) { |
HStack { |
Image(systemName: "play") |
.font(.system(size: 16)) |
Text("Next") |
.fontWeight(.semibold) |
.font(.system(size: 16)) |
} |
} |
.padding() |
.foregroundColor(.white) |
.background(Color.red) |
.cornerRadius(40) |
.shadow(radius: 5) |
} |
} |
} |
With this approach, which is basically not using the NavigationLink in my root View, the modals started to act as they should.
I can't see why but I hope it helps others.