How can I disable the swipe-back gesture in SwiftUI? The child view should only be dismissed with a back-button.
7 Answers
By hiding the back-button in the navigation bar, the swipe-back gesture is disabled. You can set a custom back-button with .navigationBarItems()
struct ContentView: View {
var body: some View {
NavigationView{
List{
NavigationLink(destination: Text("You can swipe back")){
Text("Child 1")
}
NavigationLink(destination: ChildView()){
Text("Child 2")
}
}
}
}
}
struct ChildView: View{
@Environment(\.presentationMode) var presentationMode
var body:some View{
Text("You cannot swipe back")
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: Button("Back"){self.presentationMode.wrappedValue.dismiss()})
}
}

- 7,672
- 3
- 36
- 48
-
2This works, but looses you at least the localization (i.e. internationalization) of the back button which you might care about or not. – SirVer Jan 26 '20 at 17:21
-
4is there a way to hide the back button without losing swipe-back? – bze12 Dec 30 '20 at 03:26
-
@SirVer shouldn't it be fine to use a localized string in your "Back" button? If you care about internationalization, that shouldn't be hard. – Rillieux Feb 10 '22 at 20:59
-
You also lose the back button smartness that it only shows the icon if the title does not fit. – bio Jul 03 '22 at 12:43
Only complete removal of the gesture recognizer worked for me.
I wrapped it up into a single modifier (to be added to the detail view).
struct ContentView: View {
var body: some View {
VStack {
...
)
.disableSwipeBack()
}
}
DisableSwipeBack.swift
import Foundation
import SwiftUI
extension View {
func disableSwipeBack() -> some View {
self.background(
DisableSwipeBackView()
)
}
}
struct DisableSwipeBackView: UIViewControllerRepresentable {
typealias UIViewControllerType = DisableSwipeBackViewController
func makeUIViewController(context: Context) -> UIViewControllerType {
UIViewControllerType()
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
}
class DisableSwipeBackViewController: UIViewController {
override func didMove(toParent parent: UIViewController?) {
super.didMove(toParent: parent)
if let parent = parent?.parent,
let navigationController = parent.navigationController,
let interactivePopGestureRecognizer = navigationController.interactivePopGestureRecognizer {
navigationController.view.removeGestureRecognizer(interactivePopGestureRecognizer)
}
}
}
You can resolve the navigation controller without third party by using a
UIViewControllerRepresentable
in the SwiftUI hierarchy, then access the parent of its parent.

- 15,810
- 18
- 109
- 172
Adding this extension worked for me (disables swipe back everywhere, and another way of disabling the gesture recognizer):
extension UINavigationController: UIGestureRecognizerDelegate {
override open func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
}
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}

- 61
- 1
- 1
I use Introspect library then I just do:
import SwiftUI
import Introspect
struct ContentView: View {
var body: some View {
Text("A view that cannot be swiped back")
.introspectNavigationController { navigationController in
navigationController.interactivePopGestureRecognizer?.isEnabled = false
}
}
}

- 357
- 4
- 7
Setting navigationBarBackButtonHidden
to true will lose the beautiful animation when you have set the navigationTitle
.
So I tried another answer
navigationController.interactivePopGestureRecognizer?.isEnabled = false
But It's not working for me.
After trying the following code works fine
NavigationLink(destination: CustomView()).introspectNavigationController {navController in
navController.view.gestureRecognizers = []
}

- 31
- 3
-
1This should be marked as the correct answer. The other ones you end up losing the beautiful iOS animation, as you said. – Vitor Jul 03 '21 at 01:03
-
1
This answer shows how to configure your navigation controller in SwiftUI (In short, use UIViewControllerRepresentable
to gain access to the UINavigationController
). And this answer shows how to disable the swipe gesture. Combining them, we can do something like:
Text("Hello")
.background(NavigationConfigurator { nc in
nc.interactivePopGestureRecognizer?.isEnabled = false
})
This way you can continue to use the built in back button functionality.

- 12,090
- 7
- 58
- 76
The following more replicates the existing iOS chevron image. For the accepted answer. That is replace the "back" with image chevron.
.navigationBarItems(leading: Button("Back"){self.presentationMode.wrappedValue.dismiss()})
With
Button(action: {self.presentationMode.wrappedValue.dismiss()}){Image(systemName: "chevron.left").foregroundColor(Color.blue).font(Font.system(size:23, design: .serif)).padding(.leading,-6)}

- 184
- 6