18
votes

I'm trying to push a view controller with a visible navigation bar from a view controller with a hidden navigation bar.

I tried all sorts of combinations of [[self navigationController] setNavigationBarHidden:YES animated:NO]; in viewWillAppear, viewDidAppear, viewWillDisappear... etc.

// First View Controller

@implementation FirstViewController

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [[self navigationController] setNavigationBarHidden:YES animated:NO];

    NSLog(@"[%@ viewWillAppear]", self);
}

@end


// Second View Controller


@implementation SecondViewController

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [[self navigationController] setNavigationBarHidden:NO animated:NO];

    NSLog(@"[%@ viewWillAppear]", self);
}

@end

Nothing worked. I also tried custom code to "animate" a push and pop, which works, BUT I lose the edge swipe and view panning. Before I dig deeper, just want to make sure I'm not reinventing the wheel.

The Starbucks app is what I'm trying to mimic.

The root view controller of the app (the dark background view) is full screen and notice how it doesn't have a UINavigationBar. But when you tap on one of the buttons, it pushes on a view controller (the light background view) WITH a UINavigationBar. From there, if you tap the "back" arrow, it view controller pops with the navigation bar. Interactive pop swipe gesture also works.

Starbucks iOS App

2
Is the only reason for having the navigation bar showing in in the 2nd view so that there is a back button? Or are other things (aside from the title/subtitle) that you need the navigation bar for?sfeuerstein
Definitely need the back button, but also need a functional navigation controller/bar as the user drilled deeper.YarGnawh
Ahh got it. I was going to say you could just add a custom view to the top with a back button that calls popViewControllerAnimated and keep the nav bar hidden. I suppose you still could, but I don't know how complex things get as you drill deepersfeuerstein
I'm not sure what your problem is -- you mention code to hide the navigation bar, but not code to actually push the next controller. Are you calling pushViewController:animated:?rdelmar
If you want to swipe without the auto implemented back feature, add this to your VC. I usually drop it in viewDidLoad: self.navigationController.interactivePopGestureRecognizer.delegate = self;Logan

2 Answers

30
votes

It is possible without hacking together a solution by yourself. Here is what you do:

Your root viewController:

@implementation ViewController

....

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self.navigationController setNavigationBarHidden:YES animated:animated];
}

@end

And the pushed viewController:

@implementation SecondViewController

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self.navigationController setNavigationBarHidden:NO animated:animated];
}

@end

This will do. It also keeps the interactive transition working ;)

I find it disturbing, however, that this type of functionality is not documented at all by apple. - You can also hide and show toolbars with these 'call-points' (inside viewWillAppear:)

EDIT

I just realized that this is the same code you wrote in your question. Please test it again. I am 100% sure that this works - I used this functionality in one of my apps, too.

Please also note that my code does use animated:animated instead of your animated:NO. This may be the crucial point here :)

1
votes

I just set up two view controllers to test this back and forth.

@interface VC1 ()

@end

@implementation VC1

- (void)viewDidLoad {
[super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.navigationBarHidden = YES;
}

@end

and a second

#import "ViewControllerTwo.h"

@interface ViewControllerTwo ()

@end

@implementation ViewControllerTwo

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    self.navigationController.navigationBarHidden = NO;
}

@end

VC1 is embedded in a navigationController (which is the root controller for the app), with a button that navigates to ViewControllerTwo. I have a push segue from VC1 -> ViewControllerTwo, this method works. When I tap on the button, the view controller is visible on ViewControllerTwo, when I press back, the navigationBar is gone.