After upgrading to iOS14 (14.0.1 included), all my sheet modals in my app started to act randomly weird:
Sometimes the modals act perfectly as usual
Sometimes (most of the time) I have to kill the app because the modal is not dismissed and I cannot go back to the main view
Sometimes a modal is automatically (non-desired) closed right after it opens, and after that, the modal works fine (and so it is not closed until I say so)
I tried closing the modals in two different ways: either by using the Binding<Bool> method, or by using the Environment presentationMode method, and while both methods were all working fine in iOS13, now in iOS14 they are all randomly (more than 50% of the time that I open the app) failing.
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.
App 1: No issue in iOS13 but weird modal behaviour in iOS14
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.
App 2: Issue solved (as far it seems for now)
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.