Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable back/left swipe gesture in UINavigationController after setting leftBarButtonItem?

I got the opposite issue from here. By default in iOS7, back swipe gesture of UINavigationController's stack could pop the presented ViewController. Now I just uniformed all the self.navigationItem.leftBarButtonItem style for all the ViewControllers.

Here is the code:

self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:LOADIMAGE(@"back_button") style:UIBarButtonItemStylePlain target:self action:@selector(popCurrentViewController)]; 

after that, the navigationController.interactivePopGestureRecognizer is disabled. How could I make the pop gesture enabled without removing the custom leftBarButtonItem?

Thanks!

like image 218
Itachi Avatar asked Jan 22 '16 08:01

Itachi


People also ask

How do I turn off swipe gestures in iOS?

Answer: A: As stated in this article, Switch between apps on iPad - Apple Support. To turn off the multifinger swipe gesture, go to Settings > Home Screen & Dock > Multitasking.

How do you use swipe gestures in swift 5?

A swipe gesture recognizer detects swipes in one of four directions, up , down , left , and right . We set the direction property of the swipe gesture recognizer to down . If the user swipes from the top of the blue view to the bottom of the blue view, the swipe gesture recognizer invokes the didSwipe(_:)


2 Answers

First set delegate in viewDidLoad:

self.navigationController.interactivePopGestureRecognizer.delegate = self; 

And then disable gesture when pushing:

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {     [super pushViewController:viewController animated:animated];     self.interactivePopGestureRecognizer.enabled = NO; } 

And enable in viewDidDisappear:

self.navigationController.interactivePopGestureRecognizer.enabled = YES; 

Also, add UINavigationControllerDelegate to your view controller.

like image 74
Lumialxk Avatar answered Sep 29 '22 02:09

Lumialxk


You need to handle two scenarios:

  1. When you're pushing a new view onto the stack
  2. When you're showing the root view controller

If you just need a base class you can use, here's a Swift 3 version:

import UIKit  final class SwipeNavigationController: UINavigationController {          // MARK: - Lifecycle          override init(rootViewController: UIViewController) {         super.init(rootViewController: rootViewController)           delegate = self     }          override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {         super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)                  delegate = self     }      required init?(coder aDecoder: NSCoder) {          super.init(coder: aDecoder)           delegate = self      }          override func viewDidLoad() {         super.viewDidLoad()                  // This needs to be in here, not in init         interactivePopGestureRecognizer?.delegate = self     }          deinit {         delegate = nil         interactivePopGestureRecognizer?.delegate = nil     }          // MARK: - Overrides          override func pushViewController(_ viewController: UIViewController, animated: Bool) {         duringPushAnimation = true                  super.pushViewController(viewController, animated: animated)     }          // MARK: - Private Properties          fileprivate var duringPushAnimation = false  }  // MARK: - UINavigationControllerDelegate  extension SwipeNavigationController: UINavigationControllerDelegate {          func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) {         guard let swipeNavigationController = navigationController as? SwipeNavigationController else { return }                  swipeNavigationController.duringPushAnimation = false     }      }  // MARK: - UIGestureRecognizerDelegate  extension SwipeNavigationController: UIGestureRecognizerDelegate {          func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {         guard gestureRecognizer == interactivePopGestureRecognizer else {             return true // default value         }                  // Disable pop gesture in two situations:         // 1) when the pop animation is in progress         // 2) when user swipes quickly a couple of times and animations don't have time to be performed         return viewControllers.count > 1 && duringPushAnimation == false     } } 

If you end up needing to act as a UINavigationControllerDelegate in another class, you can write a delegate forwarder similar to this answer.

Adapted from source in Objective-C: https://github.com/fastred/AHKNavigationController

like image 33
iwasrobbed Avatar answered Sep 29 '22 02:09

iwasrobbed