18

I have a view controller which is nested within a UINavigationController.

I have implemented the iOS 7 interactivePopGestureRecognizer to enable the user to gesture to pop a VC off the stack.

Within the VC i have a scrollview and whilst the user is not at the top of the scrollview I hide all the chrome (Navigation bar and status bar) to place focus on the content.

However with the navigation bar hidden, the interactivePopGestureRecognizer is not working.

I have tried enabling it after it has disappeared and verified it is not nil, however it still doesn't work.

Is there anything I am missing?

bneely
  • 9,083
  • 4
  • 38
  • 46
Dan
  • 1,447
  • 2
  • 14
  • 30

5 Answers5

38

Set your UIViewController subclass as the gestureRecognizer's delegate:

self.navigationController.interactivePopGestureRecognizer.delegate = self;

That's it!

simonmaddox
  • 790
  • 7
  • 20
  • 3
    Thanks, in fact setting it to nil also works. I wonder if this is a bug? – Dan Nov 07 '13 at 11:03
  • 17
    There will be a bug if set self.navigationController.interactivePopGestureRecognizer.delegate to self or nil: Swipe from the edge of the screen, and tap something to push a view controller into the navigation controller quickly, then -- 1. The current view controller does not respond any touch event; 2. The new view contrller will not be shown; 3. Swipe from the edge of the screen again, the new view contrller will be shown; 4. Call popViewControllerAnimated: with the animated parameter set to NO (tap the custom back button), crash! – Míng Dec 16 '13 at 12:46
  • 4
    It looks like *just* setting the delegate isn't enough, see the crash report by @iwill. The workaround we found was to store the original delegate, e.g. in `viewDidLoad`, set yourself as the new one in `viewDidAppear:` and then reset it again to the original one in `viewDidDisappear:`. Kinda strange, but works. – Dennis Feb 03 '14 at 12:57
  • 1
    @Dennis having the same problem, but I tried your solution, doesn't seem to be working. – ninjaneer Mar 09 '14 at 20:44
  • 4
    I would not recommend this solution. It resulted in several bugs when presenting/popping view controllers. – Arie Litovsky Apr 01 '14 at 19:50
  • 2
    You should set it in viewDidAppear -(void)viewDidAppear:(BOOL)animated { self.navigationController.interactivePopGestureRecognizer.delegate = self; } – Alexi Akl May 04 '15 at 13:25
  • If you want to use further `interactivePop` in your navigation stack you have to save delegate object before changing `interactivePopGestureRecognizer.delegate` and restore the initial value when `UIViewController` disappears. – malex Sep 09 '15 at 15:59
  • @iwill did you ever figure out how to do this right? Im experiencing the same exact issue you mentioned/ – user7097242 Feb 23 '18 at 19:34
  • @ArieLitovsky what would you suggest for this then? – user7097242 Feb 23 '18 at 20:20
  • @user7097242 I posted an answer https://stackoverflow.com/a/20672693/456536 – Míng Feb 27 '18 at 02:35
16

Simple solution

Just set the hidden property of the navigation bar not through navigation controller

Just use these two lines

self.navigationController.navigationBarHidden = NO;
self.navigationController.navigationBar.hidden = YES;
Nagaraj
  • 802
  • 9
  • 11
7

I used this. self.navigationController.interactivePopGestureRecognizer.delegate = self;

also in my UINavigationController class to disable interactivePopGestureRecognizer during transitions.

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

    [super pushViewController:viewController animated:animated];
}

- (void)navigationController:(UINavigationController *)navigationController
       didShowViewController:(UIViewController *)viewController
                    animated:(BOOL)animated
{
    if ([navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        // disable interactivePopGestureRecognizer in the rootViewController of navigationController
        if ([[navigationController.viewControllers firstObject] isEqual:viewController]) {
            navigationController.interactivePopGestureRecognizer.enabled = NO;
        } else {
            // enable interactivePopGestureRecognizer
            navigationController.interactivePopGestureRecognizer.enabled = YES;
        }
    }
}

the reason of disable interactivePopGestureRecognizer in rootViewController is:when swipe from edge in rootViewController and then tap something to push in next viewController, the UI won't accept any touches now.Press home button to put app in background , and then tap it to enter foreground...

hellkernel
  • 77
  • 1
  • 2
3

This doesn't seem to work for me. I followed Keithl's blog post. Neither did that work.

I ultimately settled with UISwipeGestureRecognizer. It seems to do what it says.

UISwipeGestureRecognizer *gestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(backButtonPressed:)];
[gestureRecognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self.navigationController.view addGestureRecognizer:gestureRecognizer];
Peter B
  • 22,460
  • 5
  • 32
  • 69
ThefunkyCoder
  • 81
  • 1
  • 7
0

Adding these two lines to -(void)viewDidAppear:(BOOL)animated worked for me.

self.navigationController.navigationBarHidden = NO;
self.navigationController.navigationBar.hidden = YES;

And dont forget to call <UIGestureRecognizerDelegate> to .h file.

Vaibhav Saran
  • 12,848
  • 3
  • 65
  • 75