Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

interactivePopGestureRecognizer corrupts navigation stack on root view controller

Tags:

In my UINavigationController I added custom back buttons with the side effect that it is not possible anymore to swipe left to right to pop the view controller and navigate back.

So I implemented interactivePopGestureRecognizer in my custom UINavigationController class:

class UINavigationControllerExtended: UINavigationController, UIGestureRecognizerDelegate {      override func viewDidLoad() {         super.viewDidLoad()          if self.respondsToSelector(Selector("interactivePopGestureRecognizer")) {             self.interactivePopGestureRecognizer?.delegate = self         }     }      func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {         return true     }      func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailByGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {         return gestureRecognizer.isKindOfClass(UIScreenEdgePanGestureRecognizer)     } } 

This works fine except when I am in my root view controller (RVC) which is a UICollectionViewController, i.e. the most bottom view controller in the navigation stack. When I do the swipe left to right gesture, nothing seems to happen, as expected. But when I then tap a UICollectionViewCell the destination view controller (DVC) does not get pushed over the RVC. Instead I only see the DVC's shadow on the right side of the screen.

The RVC is not responsive anymore, but as I swipe left to right again, the DVC interactively moves right to left into the screen. When I finish the gesture, the DVC moves completely into the screen just to quickly disappear left to right again. The RVC becomes responsive again.

So it seems the DVC gets pushed onto the navigation stack but not visibly into the screen.

Any suggestions where this strange behaviour originates?

like image 793
Manuel Avatar asked Jan 09 '16 19:01

Manuel


People also ask

What is Interactivepopgesturerecognizer?

The gesture recognizer responsible for popping the top view controller off the navigation stack.

How do I get navigation controller root view controller?

The root view controller is simply the view controller that sits at the bottom of the navigation stack. You can access the navigation controller's array of view controllers through its viewControllers property. To access the root view controller, we ask for the first item of the array of view controllers.

How do I add a view controller to my navigation controller?

Step 1: Embed root view controller inside a navigation controller. In your storyboard, select the initial view controller in your hierarchy. With this view controller selected, choose the menu item Editor -> Embed In -> Navigation Controller .


2 Answers

Implement UINavigationControllerDelegate for your navigation controller and enable/disable the gesture recognizer there.

// Fix bug when pop gesture is enabled for the root controller func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {     self.interactivePopGestureRecognizer?.enabled = self.viewControllers.count > 1 } 

Keeping the code independent from the pushed view controllers.

like image 57
Rivera Avatar answered Oct 05 '22 11:10

Rivera


My current solution is to disable the interactivePopGestureRecognizer in the root view controller:

override func viewDidAppear(animated: Bool) {     super.viewDidAppear(animated)      self.navigationController?.interactivePopGestureRecognizer?.enabled = false } 

In the first child view controller I enable it again. But this seems to be more a workaround because I don't understand the actual problem why the navigation stack got messed up in the first place.

like image 22
Manuel Avatar answered Oct 05 '22 12:10

Manuel