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?
The gesture recognizer responsible for popping the top view controller off the navigation stack.
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.
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 .
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With