UIStatusBar will not go away. Sadness and frustration ensues - ios

Tried everything. Just trying to hide it for one view controller.
.plist:
Status bar is initially hidden = NO
View controller-based status bar appearance = YES
view controller:
- (BOOL)prefersStatusBarHidden {
return YES;
}
//I shouldn't have to do this, the above method should suffice. Doesn't work anyway
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
}
Nothing works. Status bar is still there, staring me in the face, laughing through it's ugliness. What do I need to do???
EDIT: prefersStatusBarHidden does not even get called. This view controller is pushed onto the navigation stack via push segue.

In any custom containing view controller, implement childViewControllerForStatusBarHidden, returning the current child view controller that should controller the status bar appearance (in this case, the navigation controller).
This will let the system follow the view controller hierarchy down to the current "top" view controller, and it's that view controller's prefersStatusBarHidden which will be queried.
In your custom containing view controller, if the current "active" child view controller changes, call setNeedsStatusBarAppearanceUpdate to let the system know.

The key here was that this was never getting called in the view controller:
- (BOOL)prefersStatusBarHidden {
return YES;
}
Tracing backward, it was not called in the parent navigation controller either. This is because the nav controller was owned by a root view controller. The root view controller did call this method, but did not pass it on to the nav controller, and thus not to any other child view controllers. So for anyone having the same issue and trying to debug, try to track down the view controller at the "root" of your hierarchy.
So in my case, I post a notification from any view controller (viewWillAppear) that I want to hide the status bar. This notification is then consumed by the root controller:
- (void)hideStatusBar:(NSNotification *)notification {
self.hideStatusBar = YES;
[self setNeedsStatusBarAppearanceUpdate];
}
Which forces this method to be called on the root controller:
- (BOOL)prefersStatusBarHidden {
return self.hideStatusBar;
}
And everything works as expected. The same can be done for showing the status bar again.

Related

Multiple segues remove navigation bar in view controller

I have a view controller that has a navigation bar. It is the root view controller of the navigation controller. I have another view controller that can be segued from a button on the first controller. Up to this point, everything works fine; there are navigation bars on both view controllers.
However, from the second view controller, I want to be able to segue back to the first controller. When doing this, it removes the navigation bar from both of the view controllers.
How can I get the navigation bar on both view controllers with buttons as transitions? Thanks!
Implement below method in your both viewcontroller,
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
You may hiding navigationbar somewhere.
Try this in storyboard:
Select the navigation controller -> Attributes Inspector -> Under Navigation controller and Bar Visibility leave the "Show navigation bar" blank

Disabling navigation bar on segue when searching

I've got an iOS app that's using a table view with a search bar added to the table view. When a row is tapped, I push another view controller that shows the details of the row that was tapped.
Our table view and detail view both hide the navigation bar.
When the search bar is not active, the navigation bar is disabled on the detail view controller, which is expected.
However, when search is active, the navigation bar shows up on the detail view controller. From what I've read, that's the default behavior for any transitions that occur when search is enabled. Is this accurate?
If so, is there anything I can do to hide the navigation bar? More generally, is there anything I can do to have the push of the detail controller behave the same way regardless of whether search is active or not?
This works
-(void)viewDidLayoutSubviews
{
self.navigationController.navigationBarHidden = YES;
self.navigationController.navigationBar.translucent = YES;
}
In your detail view controller try putting :
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:animated];
}
Link to doc

View Controller Containment shared parent objects

I am using view controller containment, and as part of my implementation a child view controller needs to disable a bar button item of the navigation controller of the parent view controller. The theory is that being a child view controller, I had access to the same navigation controller (in my context anyway) as the parent view controller's.
From debugging I can see that self.navigationController and self.parentViewController.navigationController were set to the same address.
For example:
NSLog(#"%# - %#", self.navigationController,
self.parentViewController.navigationController);
NSLog(#"%# - %#", self.navigationItem,
self.parentViewController.navigationItem);
NSLog(#"%# - %#", self.navigationController.navigationItem,
self.parentViewController.navigationController.navigationItem);
Resulted in the following console log:
<UINavigationController: 0xc482290> - <UINavigationController: 0xc482290>
<UINavigationItem: 0xa5f3620> - <UINavigationItem: 0xc482490>
<UINavigationItem: 0xa5f36e0> - <UINavigationItem: 0xa5f36e0>
Results
Navigation controllers are the same, as expected (self->navController == self->parent->navController).
Navigation item's are different, this is expected. Each view controller has it's own nav item (self->navItem != self->parent->navItem).
Accessing the navigation controllers nav item from the parent or the child view controller is identical, as expected (self->navController->navItem == self->parent->navController->navItem)
So I now ask: why didn't disabling a bar button item in the child view controller with the following code work:
self.navigationController.navigationItem.rightBarButtonItem.enabled = NO;
This should be synonym to the following (which does work as expected) given their shared address:
self.parentViewController.navigationController.navigationItem.rightBarButtonItem.enabled = NO;
Update
I was reading my logs too fast. Indeed the parentViewController and the navigation controller have 2 different navigation items. I missed this in my example here because the memory addresses were extremely close: 0xa5f3620 != 0xa5f36e0
A UINavigationController has it's very own navigationItem (like any other UIViewController) that will only come into play if you push it onto the stack of another UINavigationController.
Generally you aren't going to push one UINavigationController onto another so manipulating self.navigationController.navigationItem is pointless.
EDIT:
To check ... I've just aded:
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UINavigationItem *myNavControllersItem = self.navigationController.navigationItem;
UINavigationItem *myItem = self.navigationItem;
NSLog(#"%# - %#", myNavControllersItem, myItem);
}
to a VC that I'm pushing onto a NavController and get:
<UINavigationItem: 0x1ed0c170> - <UINavigationItem: 0x1ed46330>
Additionally, if I add:
self.navigationItem.rightBarButtonItem.enabled = NO; to viewDidAppear the right button gets disabled.
if I add:
self.navigationController.navigationItem.rightBarButtonItem.enabled = NO; it does not.
Well basically the problem is the way the navigation controller updates the bar button items, basically the buttons are update whenever the top-level child is changed.
For the right bar button item, if the new top-level child has it's own bar buttons items then the navigation controller will select the existing one, if not nothing will be displayed.
So in your case the parrentViewController already has a navigationItem.rightBarButonItem which is not disabled, by calling self.navigationController.navigationItem.rightBarButtonItem.enabled = NO; you are disabling the child's nabigationItem.rightBarButtonItem and you can't see this because the updates are made only when the top-level child is changed which is not your case.
So in order to disable the parentViewController right button you should do:
self.parentViewController.navigationItem.rightBarButtonItem.enabled = NO
For more details regarding the nav bar button updates please check apple docs regarding the Updating Navigation Bar Items

UISplitViewController doesn't hide masterViewController in landscape mode

NOTE:
Before reading this question please note that I have read the previous questions that explain the deficiencies regarding apple's implementation of UISplitViewController and how I should use the open-sourced "MGSplitViewController" because its not too easy to simply hide the master view controller on a split view controller in landscape-mode. Please keep in my mind that I'm limited to using the normal UISplitViewController in iOS 5.1.
Now onto the question:
I have a split view controller with table views on the left side (master view) and a detail view controller on the right. I'm using a navigation controller to control the left side which is a table view that transitions onto another table view ("DataTableViewController"). In order to hide this left side, I have placed a "hide" button on the navigation tool bar of the detail view controller. When the hide button is pressed, I change my "_hideMaster" property:
-(IBAction)hidePressed
{
_hideMaster = !_hideMaster;
// Must manually reset the delegate back to self in order to force call "shouldHideViewController"
self.splitViewController.delegate = nil;
self.spliteViewController.delegate = self;
}
and then automatically this method is called in the SplitViewController delegate:
// This is called when I change the delegate from nil back to self.
- (BOOL)splitViewController: (UISplitViewController*)svc shouldHideViewController: (UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation
{
return _hideMaster;
}
When I debug it, I can see that everything goes according to plan and the property has the correct value when it enters the method splitViewController:shouldHideViewController:inOrientation:
The only problem is that nothing happens. My left most table view (DataTableViewController) does not disappear. When I look closer, the (UIViewController *)vc parameter in the delegate method is not the table view controller that I want to hide but instead the navigation controller associated with this table view. So essentially it is trying to hide the navigation controller - which is clearly not what I want...
How can I make it so that the UIViewController parameter in the automatically called delegate method (shouldHideViewController:) calls the topmost view controller associated with that navigation controller? (After all, I want to hide DataTableViewController)
Here's how I handle it. Might need more work for making the MasterViewController reappear if it is not instantiated on the way back.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.30f];
[[self.splitViewController.viewControllers lastObject] view].frame = self.splitViewController.view.frame;
[UIView commitAnimations];

Set navigation bar hidden, depending on how the view controller appeared

I have a tab bar with a navigation controller in one of the tabs. Currently the root view of the navigation controller doesnt have the nav bar showing and animates nicely into the subviews by
- (void)viewDidLoad {
...
[self.navigationController setNavigationBarHidden:YES animated:NO];
...
}
and
- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
But of course changing tabs initiates the viewWillAppear function and so as I go back to the root view the navigation bar slides away, rather than just not being there.
Is there a way that I can hide the nav bar on the root view without animating it except for when appearing from a subview on the navigation stack?
The (BOOL)animated parameter on viewWillAppear:animated. When changing Tabs, it will come as NO, since the animation is immediate. On the other hand, if it's being pushed or popped from the navigation stack with animated:YES, then it will come as YES.
Although this looks like a hack, it's the correct way: you don't need to figure out who was the caller, instead, focus on the fact that if your view controller will appear animated, you have time to do your own animations, if not, screw it, show (or in this case, hide) everything immediately.
Try showing/hiding the bar in the UINavigationController's delegate's navigationController:willShowViewController:animated: method, depending on whether the view controller being shown is your root view controller.
What if you set a boolean variable in your application delegate and in set that boolean accordingly in subviews as 0 and in other views as 1. And in your viewwillappear, according to your variable's value, you can set the animation.

Resources