I have an application with 2 viewcontrollers, ViewController and NextViewController. ViewController does not have a navigation bar and has a white status bar. NextViewController does have a navigation bar and has a black (default) status bar. I have encountered a bug when swiping back to ViewController from NextViewController and cancelling the swipe where the navigation bar on NextViewController will disappear. The storyboard simply has the two views with a button and an action segue. The bug does not always happen, but often enough to be a problem. The bug has to do with the method - (UIStatusBarStyle) preferredStatusBarStyle, as everything works fine when I remove the methods.
Can I somehow stop this bug from happening while still having a white status bar on my ViewController and having the swipe enabled or am I forced to remove either functionality?
ViewController
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setNeedsStatusBarAppearanceUpdate];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
- (UIStatusBarStyle) preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
NextViewController
#implementation NextViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setNeedsStatusBarAppearanceUpdate];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleDefault;
}
Other possibly relevant info: Experiencing the issue on an iPhone 5s with iOS 8, but it also happens on the simulator with iOS 9. View controller-based status bar appearance is set to the default, YES.
Status bar style depends on - preferredStatusBarStyle of the view controller if the navigation bar is hidden, otherwise of the navigation controller, so the - preferredStatusBarStyle in your NextViewController is useless.
It seems that the bug is related with the status bar style of the navigation controller, you can subclass UINavigationController override the method childViewControllerForStatusBarStyle to avoid the bug.
#implementation MyNavigationController
- (UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
#end
Now the status bar style will depend on the view controller no matter whether the navaigation bar is hidden or not. And the bug would not happend.
Related
as picture : when the white controller in popping out with a interactive pop gesture , the red controller (which make the status bar hide) will show, and during the animation : the navigation bar seems to move up , and the controller's view is still in its position (not move up with navigation bar) ,so the view seems divided into two pieces in the pop out animation . how to fix it ?
In the first controller,add this code.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
I knew its a duplicate. But still having an issue and even when tried with possibilities didn't work. Hence posting the same to reach a solution. Hope to get help from you guys.
The initial is embedded inside UINavigationController. For the initial (the landing view) the navigation bar must be hidden. The other views when called from the landing view - must show the navigation bar.
I'm handling the hide & show of navbar in the landing view by overriding the methods of the view as follows:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// Hiding the navigationbar hidden for the first page
[[self navigationController] setNavigationBarHidden:YES animated:YES];
}
// Even tried animated:NO & animated:animated
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
// Showing the navigationbar hidden for the first page
[[self navigationController] setNavigationBarHidden:NO animated:YES];
}
While the app loads initially, the nav bar is in hidden state (as expected & working fine). When coming back to the landing view from the child view controller, the nav bar gets hidden after some seconds - the landing view gets loaded on to the ui screen.
I also tried using the navigationcontroller delegate method in landing view: navigationController: willShowViewController: animated:. But unable to reach the solution that i need.
Hence i provided the navigationcontroller delegate in one of my childviewcontroller and checked whether the childcontroller when popped is not in viewcontrollers of the navigationcontroller using if condition. When yes, then i provided the hide option of the navigationbar. but also failed to have the solution.
During surfed, there was a solution to handle with viewanimation. I tried and that too failed.
Again surfed, the solution provided across is to handle the similar issue with viewwillappear & viewwilldisappear. I'm blinked since the way i'm doing is similar to the proposed way. Even then unable to reach a solution.
FYI.. I'm using Xcode 6.3 and deployment target is 6.0 onwards. I'm using storyboard to manage views.
Please help me sort the issue... App loads is hiding the nav bar in landing page. But when landing page is loaded back from a child view then the nav bar gets hidden only after the landing page loaded on to the ui. I do need to get hidden of the nav bar as like when app loads, when the child view pops and the landing view gets loaded on the top of the controller.
If you want to hide navigation bar in the second view then don't try to manage in viewWillAppear and viewWillDisappear because I have faced a lot of problems by trying like that and it also effected the constraints. Just use delegate for navigation controller in appDelegate it is working fine for me.
self.navigationController.delegate = self;
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([viewController isKindOfClass:[LoginViewController class]])
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
} else {
[self.navigationController setNavigationBarHidden:NO animated:animated];
}
}
Use this method:
[navigationController setNavigationBarHidden:YES];
So, if you are in some view controller:
[self.navigationController setNavigationBarHidden:YES];
More clarifications:
UINavigationController has a property navigationBarHidden, that allows you to hide/show navigation bar for whole nav controller.
Let's look at the next hierarchy:
--UINavigationController
----UIViewController1
----UIViewController2
----UIViewController3
Each of three UIViewController will have nav bar since they are in UINavigationController. For example, you want to hide bar into the second (actually it doesn't matter in which one), then write into UIViewController2:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES]; //it hides
}
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:NO]; // it shows
}
Overwrite the delegate method in your custom UINavigationController class:
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[self setNavigationBarHidden:NO];
if ([viewController isKindOfClass:[SomeViewController class]])
{
[self setNavigationBarHidden:YES];
}
}
One advantage for putting it in your UINavigationController class is that you don't clutter your UIViewController class with code
Tested and works.
UPDATE
Create a UINavigationController subclass: f.e. MyNavigationController
In AppDelegate.h:
#import "MyNavigationController.h"
#property (nonatomic) MyNavigationController *navigationController;
Then initialise it in AppDelegate.m:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//Probably some more code here
self.navigationController = [[MyNavigationController alloc] initWithRootViewController:yourRootViewController];
self.window.rootViewController = self.navigationController;
self.window.backgroundColor = [UIColor blackColor];
[self.window makeKeyAndVisible];
return YES;
}
Then overwrite the delegate method in your custom UINavigationController class
I have little to no experience with storyboards so not really sure how to setup a custom UINavigationController, but this is how I do it in code.
Here's another SO post how to create a custom UINavigationController to use with storyboards.
I have three view controllers that are connected to a tab bar controller, which I thought should automatically set the presentingViewController/presentedViewController. However, when I toggle between my view controllers and I log [self presentingViewController], it logs null. I put the log in my viewDidAppear methods in each of the view controllers.
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
NSLog(#" my presenting view controller is %#", [self presentingViewController]);
}
Output:
my presenting view controller is (null)
If you want to know which tab you came from, then you should subclass the tab bar controller, and set it as its own delegate. Create an integer property, oldIndex which you can set before the tab switch in the delegate method, tabBarController:shouldSelectViewController:.
#interface RDTBC () <UITabBarControllerDelegate>
#end
#implementation RDTBC
- (void)viewDidLoad {
[super viewDidLoad];
self.delegate = self;
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
self.oldIndex = self.selectedIndex;
return YES;
}
Then in your view controller, you can get it like this,
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(#"%ld",[(RDTBC *)self.tabBarController oldIndex]);
}
It's probably not a good idea to make one tab's behavior dependent on what tab was last shown. Tabs are designed to function independently.
I have trouble w/ hiding toolbar when leave screen by segue.
Details: App has a few dozen screens, all of them are belonged the same navigation controller. A few screens have toolbar. For these a few screens in -(void)viewDidLoad I use
[self.navigationController setToolbarHidden:NO animated:NO];
and in -(void)viewWillDisappear:(BOOL)animated:
[self.navigationController setToolbarHidden:YES animated:YES];
so toolbar is visible only on necessary screens and the screen which needs toolbar controls the visibility. All work well when I navigate by "back" button.
The trouble starting when I try to navigate by segue like this (goto home & goto another branch).
[owner.navigationController popToRootViewControllerAnimated:NO];
[self performSegueWithIdentifier:SEGUE_NAME sender:self];
toolbar is stay visible in spite of calling -(void)viewWillDisappear which should hide toolbar.
are there any ideas how to perform these "ToolBarHidden" by right way.
thanks
PS: of course I could hide toolbar on every screen, but I want to avoid this unnecessary operations and want to know how to do it right.
**STEP1:** in your controller.h
#interface ViewController : UIViewController {
UIToolbar *bar;
}
#property (nonatomic, strong) IBOutlet UIToolbar *bar;
#end
**STEP2:** in your controller.m
#synthesize bar;
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.bar.hidden = NO;
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
self.bar.hidden = YES;
}
**STEP3:** connect in Intrface
hope this help you!
I have the following problem: I have overridden popViewControllerAnimated:(BOOL)animated of UINavigationController because I would like to have a custom animation. The code is as follows:
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
UIViewController *poppedCtrl = [super popViewControllerAnimated:NO];
[((customViewController *) self.topViewController) doCustomAnimation];
return poppedCtrl;
}
Unfortunately the UINavigationBar seems to ignore that I explicitly disable the built in animation and it is still animated.
What do I have to do to also prevent the animation of the navigation bar?
After some reading and also some experimentation I finally found out what needs to be done to achieve the desired behavior.
To prevent the navigation bar from being animated it is not sufficient to override (UIViewController *)popViewControllerAnimated:(BOOL)animated.
It is also necessary to create a custom navigation bar and override (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated:
- (UINavigationItem *)popNavigationItemAnimated:(BOOL)animated {
return [super popNavigationItemAnimated:NO];
}
Of course this custom navigation bar must also be the one which is used (I just replaced the navigation bar which is used by my navigation controller in the interface builder).
If anyones looking to disable push animation - this works for me, by overrideing this method on UINavigationBar:
- (void)pushNavigationItem:(UINavigationItem *)item {
NSMutableArray* items = [[self items] mutableCopy];
[items addObject:item];
self.items = items;
}