'Disable swipe back gesture in Swift
Been looking around on here for a while but can't seem to find a working solution.
I'm trying to disable the swipe to go back to previous view gesture, in Swift.
I've tried a variety of solutions including:
self.navigationController?.interactivePopGestureRecognizer.enabled = false
and
self.navigationController.interactivePopGestureRecognizer.delegate = self
func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer!) -> Bool {
return false
}
Is there a new method of doing this or some other method that works?
Solution 1:[1]
You could disable it but that would not be to recommended as most iOS users go back by swiping and less by pressing the back button.
If you want to disable it it would be more reasonable to use a modal segue
instead of a push segue which is not that big of a transfer.
If you really want to get rid of the swipe to go back function I would just disable the back button and have a done button on the top right of the screen.
self.navigationController?.navigationItem.backBarButtonItem?.isEnabled = false;
Solution 2:[2]
The following is an easy approach to disabling & re-enabling the swipe back.
Swift 3.x & up
In a viewDidLoad/willAppear/didAppear method add:
navigationController?.interactivePopGestureRecognizer?.isEnabled = false
Just keep in mind that if you do it with viewDidLoad
, then the next time you open the view, it may not be set depending upon whether or not it remains in your stack.
Unless you want it to remain off, you will need to turn it back on when the view is closed via either willMove(toParentViewController:)
or willDisappear
. Your navigationController
will be nil at viewDidDisappear
, so that is too late.
navigationController?.interactivePopGestureRecognizer?.isEnabled = true
A special note on SplitViewControllers:
As pointed out by CompC in the comments, you will need to call the second navigation controller to apply it to a detail view as such:
navigationController?.navigationController?.interactivePopGe??stureRecognizer?.isE??nabled = false
Swift 2.2 & Objective-C
Swift versions 2.x & below:
navigationController?.interactivePopGestureRecognizer?.enabled
Objective-C:
self.navigationController.interactivePopGestureRecognizer.enabled
Solution 3:[3]
I was able to do this by returning false in gestureRecognizerShouldBegin
class ViewController2: UIViewController, UIGestureRecognizerDelegate {
...
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationController?.interactivePopGestureRecognizer.delegate = self
}
func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
Solution 4:[4]
Add this line before pushing view controller to navigation controller
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
Solution 5:[5]
Nothing wrong with either answer from Hari or Stefan but this is more succinct. Just put it in viewDidLoad and you're done.
if navigationController!.respondsToSelector(Selector("interactivePopGestureRecognizer")) {
navigationController!.view.removeGestureRecognizer(navigationController!.interactivePopGestureRecognizer)
}
EDIT:
One small caveat is that if the Navigation Controller was opened by another view and the Navigation Controller is closed then you'll get an EXC_BAD_ACCESS error. To fix it you have to save the original UIGestureRecognizer and put it back when you exit the view.
Declare:
private var popGesture: UIGestureRecognizer?
Immediately before removing the gesture:
popGesture = navigationController!.interactivePopGestureRecognizer
Then when closing the view:
If popGesture != nil {
navigationController!.view.addGestureRecognizer(popGesture!)
}
Solution 6:[6]
RowanPD's logic for Swift 4
private var popGesture: UIGestureRecognizer?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if navigationController!.responds(to: #selector(getter: UINavigationController.interactivePopGestureRecognizer)) {
self.popGesture = navigationController!.interactivePopGestureRecognizer
self.navigationController!.view.removeGestureRecognizer(navigationController!.interactivePopGestureRecognizer!)
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let gesture = self.popGesture {
self.navigationController!.view.addGestureRecognizer(gesture)
}
}
Solution 7:[7]
Instead of
self.navigationController.pushViewController(VC, animated: Bool)
call
self.navigationController.setViewContollers([VC], animated: Bool)
setViewControllers
replaces the all the VCs on the stack, instead of adding a new controller on top. This means that the new set VC is the root VC, and the user cannot go back.
This is most effective when you only want to disable the swipe on a single VC, and keep the swipe-to-back for the other VC.
If you want users to be able to go back, just not through swiping, do not use this method as it will disable all backs (as there is no VC to go back to).
Solution 8:[8]
for objective -c
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:true];
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
Solution 9:[9]
I generally make sure that swipe back is enabled in as many places as possible, even adding a custom gesture recognizer to add it to modal screens. However for an authentication and download process in my app I start the process with a modal navigation controller and then push the view for each next step. However, once it's completed I want to prevent them from backing up into the authentication screens.
For this scenario I've been using:
navigationController?.interactivePopGestureRecognizer?.isEnabled = false
navigationItem.hidesBackButton = true
in viewWillAppear()
on the final screen. You can undo these in viewWillDisappear()
if you're pushing another view and need them there.
Solution 10:[10]
This is something you missed if it doesn't work after you tried all.
- Add
navigationController?.interactivePopGestureRecognizer?.isEnabled = false
to your viewWillAppear(animated:) method. - if it doesn't work, remove navigation delegate from the view controller. Check again if your view controller is confirming
UINavigationControllerDelegate
,UIGestureRecognizerDelegate
protocols. if so, just remove it.
Solution 11:[11]
Come here a little bit late. In my case self.navigationController?.navigationItem.backBarButtonItem?.isEnabled = false;
not working. So I do this: you can present view controller instead of push view controller. This way the swipe back gesture will not apply to the view controller.
navigationController?.present(vc, animated: true)
You could use dismiss for your custom back button
self.dismiss(animated: true)
Note: You could set VC modal presentation style before present it to make sure it's full screen.
vc.modalPresentationStyle = .fullScreen
Hope this help.
Solution 12:[12]
If requirement is to show side menu on some of the screens then add AddScreenEdgePanGesture on this specific view instead of navigationController view
replace it
SideMenuManager.default.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController?.view)
with this
SideMenuManager.default.menuAddScreenEdgePanGesturesToPresent(toView: self.view)
Solution 13:[13]
If you don't care about system back button appearance (for example, if you're using custom back button or navigation bar is hidden at all), it might help you:
navigationItem.hidesBackButton = true
It hides back button and disables swipe back gesture.
Solution 14:[14]
Only complete removal of the gesture recognizer worked for me (from the presenting view controller).
if let navigationController = parent.navigationController,
let interactivePopGestureRecognizer = navigationController.interactivePopGestureRecognizer {
navigationController.view.removeGestureRecognizer(interactivePopGestureRecognizer)
}
Solution 15:[15]
Don't Use this if you don't want to come back, or you set the new rootViewController.
self.navigationController.pushViewController(VC, animated: Bool)
Use this
self.navigationController.setViewContollers([VC], animated: Bool)
setViewControllers Remove all the View Controllers on the stack then the user cannot go back. it will disable all backs
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow