1

So iOS 7 introduced this new feature that you can pop a view controller by panning on the left edge. Here is my problem: I have two view controllers, A and B, that are connected by a push segue. Both of the controllers have navigation bars (by embedding A in a navigation controller). The navigation bar in B will be hidden once the user enters B's scene, and can be shown if the user taps on the scene. If the user pans on the left edge of B while the navigation bar is hidden, the navigation bar in A will be hidden as well, which means that there is no way for the user to return further back from A. So is there a way to enforce A to always show the navigation bar regardless of B has hidden the bar or not? Or is there a easy way to prevent the pan gesture from taking effect? I read this post which suggested a way of preventing the pan, but I can't locate the property in storyboard.

EDIT: So I disabled the interactive pop gesture recognizer but that only solved half of the problem. The other half is that if I click the back button on the child view controller navigation bar when the navigation bar is disappearing, I am navigated back to the parent view controller without a navigation bar. I tried calling [self.navigationController setNavigationBarHidden:NO] in viewWillAppear and then viewDidLoad but it does not work. Is this some sort of bug in the SDK or am I missing something?

Here is the code for hiding the navigation bar in the child view controller

- (void)hideNavigationBar
{
    if (self.navigationBarHidden == NO)
    {
        [UIView animateWithDuration:UINavigationControllerHideShowBarDuration animations:^{
            self.navigationController.navigationBar.alpha = 0.0;
            self.previewCollectionView.alpha = 0.0;
        } completion:^(BOOL finished) {
            self.navigationBarHidden = YES;
        }];
    }
}
Community
  • 1
  • 1
ljiatu
  • 511
  • 7
  • 22

2 Answers2

1

Yes, you can enforce the navigation bar's appearance in the A viewController's -viewWillAppear method.

Also, since you cannot find the interactivePopGestureRecognizer property in the storyboard, you can use this line in the A viewController's -viewDidLoad method:

self.navigationController.interactivePopGestureRecognizer.enabled = NO;

EDIT:

In the viewWillAppear method, you will have to call:

[self.navigationController setNavigationBarHidden:NO];
self.navigationController.navigationBar.alpha = 1.0;
ZeMoon
  • 20,054
  • 5
  • 57
  • 98
  • Sweet! I solved the problem by disabling the gesture recognizer. But I wonder how it was enabled though. Isn't the disable the default for that property? In my app, A is also connected to another view controller C by a push segue, but the pan gesture does not work on C. – ljiatu Apr 06 '14 at 16:49
  • I got a new problem... Please see the edit section in the original problem. – ljiatu Apr 08 '14 at 23:30
  • Calling `self.navigationController.navigationBar.alpha = 1.0` works! – ljiatu Apr 10 '14 at 16:10
1

I see a couple problems with your situation:

  1. You disable the interactive pop gesture and you hide the nav bar from view controller B. How is the user supposed to intuitively go back?

  2. The animation that hides your navbar in B may be causing the issue. If it's anything longer than a split second, that animation may not complete in time before you hit the back button and -viewWillAppear fires on A.

  3. Your code in B hides the navigation bar for the navigation controller. The navigation controller that holds view controller A is the same instance that holds view controller B. If you hide the navigation bar when B loads, then you go back to A (not sure how you're doing that without a back button or a edge pan gesture), it should still be hidden.

You probably want NOT disable the gesture (so the user can intuitively go back) and turn the navigation bar back on in view controller A's -viewWillAppear, to cover the case where you turned it off in B:

if (self.navigationBarHidden == NO)
{
    self.navigationController.navigationBar.alpha = 1.0;
    self.previewCollectionView.alpha = 1.0;
    self.navigationBarHidden = NO;
}
Aaron
  • 7,055
  • 2
  • 38
  • 53
  • If the user performs a single tap, the navigation bar comes back, and that's how they go back to view controller A. – ljiatu Apr 09 '14 at 17:18
  • So when they bring the navigation bar back, then they tap "back" is the navigation bar hidden on A? – Aaron Apr 09 '14 at 17:20
  • Nope, it is shown and it's what I expected. What I'm not expecting is that even though I enforced the bar to be shown in A it is still hidden when the bar is on its way hiding itself in B. Your explanation makes sense. Can you elaborate on your code though? – ljiatu Apr 09 '14 at 17:54
  • So, I'm still confused about what you're issue is. So ... you tap back, as the bar is hiding itself via an animation? And then when the pop completes, the bar is hidden in A, even though you un-hide it in A's `-viewWillAppear`? Do I have that right? My code would undo what was done by the animation in B, without the animation. I suggest hiding/showing the bar w/o animating it and see if that makes a difference. If it does the problem might be a race condition with the animation. – Aaron Apr 09 '14 at 18:05
  • Yes, I tried to tap back while the bar is hiding via an animation. And the bar is hidden even though I force it to show up in A's `viewDidAppear`. – ljiatu Apr 09 '14 at 23:50
  • I'm suggesting that you try to hide the nav bar in B without animation and see if that might be the problem. – Aaron Apr 10 '14 at 01:48
  • It does fix the problem because there is no way I can tap on the back button when it is hiding itself (it hides it self too quickly). – ljiatu Apr 10 '14 at 02:39
  • So that said, I think the issue is indeed race condition (probably `viewdidAppear` is finished before the bar is completely hidden). The hidden without animation is not quite a desirable behavior for the app . Any suggestion for a workaround? – ljiatu Apr 10 '14 at 03:50
  • Let me think on it and get back to you. There are a couple approaches that you could take – Aaron Apr 10 '14 at 04:40
  • I really appreciate it! – ljiatu Apr 10 '14 at 04:43
  • You could 1) ditch the animation that hides the nav on B after the user taps "back" because why hide it if you know you'll need it on A? So leave the nav there if they hit the back button. 2) only pop back to A after the hide animation is complete. This would avoid the race condition and possibly make for some weird animations. This would also require that you unhook the segue (if you're using them) and call pop view controller on B when the hide nav animation completes. I'm sure there's other stuff you can do too. – Aaron Apr 10 '14 at 04:57
  • Actually I solved the problem by setting the alpha value of the navigation item in A back to 1 in `viewDidAppear`. This works probably because in B the navigation item is actually not hidden, but set to be transparent. So calling `setNavigationBarHidden:NO` will not show the nav bar because the nav bar is there already. But thanks for your suggestions! – ljiatu Apr 10 '14 at 16:09