Search code examples
iosswiftuiswiftui-navigationview

How to disable `Back` gesture in `NavigationView`?


I need to disallow the Back swipe gesture in a view that has been "pushed" in a SwiftUI NavigationView.

I am using the navigationBarBackButtonHidden(true) view modifier from the "pushed" view, which obviously hides the standard Back button, and partially solves for the requirement.

But users cans still swipe from left to right (going back), which I don't want to allow.

I have tried using interactiveDismissDisabled, but this only disables swiping down to dismiss, not "back".

Any suggestions welcome.

[UPDATE] I tried creating a new app with Xcode 14.2, and the navigationBarBackButtonHidden(true) worked as expected:

  1. No back button
  2. Back swipe gesture disabled

But when I modified the main class of my existing app - with the EXACT SAME CODE as the new test app, it still allowed the back swipe gesture. Here's the code:

import SwiftUI

@main
struct MyApp: App {
    
    var body: some Scene {
        WindowGroup {
            MyView()
        }
    }
}

struct MyView: View {
    
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink("Next page") {
                    Text("Page 2")
                        .navigationBarBackButtonHidden(true)
                }
            }
        }
    }
}

At this point, I'm fairly confused. Recreating my existing project, that was created with Xcode 13, will be a substantial task, so I'm trying to figure out what's different. I'm assuming that there is some build setting or configuration option that is somehow influencing this behavior.

Again, any suggestions welcome


Solution

  • It turns out that we had the following code in our app that was thought to be unused, but really wasn't, since it was extending UINavigationController.

    extension UINavigationController: UIGestureRecognizerDelegate {
        override open func viewDidLoad() {
            super.viewDidLoad()
            interactivePopGestureRecognizer?.delegate = self
        }
    
        public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
            return viewControllers.count > 1
        }
    }
    

    Uggh.