UINavigationController TitleView not displayed from ViewController NavigationItem - iphone

Whenever I add a viewController to a navigationController while in landscape the title view appears on certain views but not on others. ie: I have a navigation controller, add 3 view controllers, first two show titleview appropriately, third one doesn't show one at all. But the navigation controller grabs the titleview from the ViewController like it's supposed to, I wrote the value of it to the console and it is correct, but it just doesn't show on the screen for whatever reason. Any ideas?
Oh yeah works perfectly while in portrait orientation.
Here's another fun part, if I push the trouble view controller into the navigationController in landscape the titleView isn't there, then without any user interaction, I rotate the device back to portrait and the titleView appears, then I rotate the device back to landscape and it stays!
It's like the drawing of my TitleView was blocked even though I used InvokeOnMainThread. Nothing is running in the main thread (or anywhere for that matter) during that call.
Here's my structure:
Window
TabBarController
NavigationController
ViewController
NavigationController
ViewController
Here's my order of operations:
Create View Controller
Add Title view to view controller
Push View Controller onto NavigationController (InvokeOnMainThread)

Have you tried setting the controller title after the controller is pushed? This kind of behavior happens to me and the way to make sure the title appears is to mandatory set the navBar title in the viewDidLoad or viewWillAppear method as follows:
self.navigationController.navigationBar.topItem.title = #"The title";
or
self.navigationItem.title = #"The Title";
Other thing that happened to me is to set the leftBarButton or RightBarButton of a navigation bar without success in the viewDidLoad method, but they appear correctly when setting the bar buttons in the viewWillAppear method.
Hope this helps.

I think your problem maybe that when your function is called, the navigation item is nil. So when you call self.navigationITem.title, it do nothing. Later, when the view is rotated, the navigationItem is not nil anymore so changing the title works.
If you do the code in ViewDidLoad function beware that ViewDidLoad is called the first time someone calls viewController.view and not the first time the view is displayed. So the view may not be in a navigationController yet.
For example, this can happend if you do :
viewController.view.backgroundColor = ... ;
[navigationController pushViewController:viewController]
The first line will call ViewDidLoad even if the controller is not in a navigationController yet.

Related

Put common code for UINavigationBar in UINavigationController

In my iPhone project, I have a navigation view controller. In each view that is loaded by this controller, I am setting buttons in the UINavigationBar that are doing different things for each view.
However, I want to have the .rightBarButtonItem do exactly the same thing each time (namely, pop up a UIActionSheet). How can I centralize this code and not have to put it in every view controller?
I tried subclassing UINavigationController and setting the .rightBarButtonItem in this subclass' viewDidLoad. However, no button is displayed then. (But when I put the same code in a view controller loaded by the navigation controller, the button is displayed and works fine).
The code I am using to set the rightBarButtonItem is:
self.navigationItem.rightBarButtonItem = ...
Subclass all the UIViewControllers that are pushed onto that UINavigationController and add the same viewDidLoad code.

popToRootViewControllerAnimated doesn't modify attached navigationItem

My UIViewController calls a function on my rootViewController which then called popToRootViewControllerAnimated to return the view to the rootController. This all works - great!
Unfortunately the UINavigationItem (toolbar at the top) seems to display a mashup of both the rootViewController and the UIViewController that has just been removed.
What do I need to do? What have I done wrong?
The navigation bar doesn't remember changes that were made to it, so when you push a new controller, the navigation bar is altered to give the title of the new view controller, but it doesn't store what was there for the previous view controller.
You will need to recreate the items in the toolbar each time you come back to the view controller that has custom items.
You might be able to do this on viewWillAppear instead of viewDidLoad. I can't recall exactly, but you should recreate custom controls on navigation toolbar because it does not get preserved when a new view controller is pushed.
It seems that calling popToRootViewController from the rootViewController messes things up. TO rectify this I called the following from within the calling UIViewController
[self.navigationController popViewControllerAnimated:YES];

View sizing with setting navigationbar to hidden with push/pop

So before I push a new viewController onto the stack in a certain view, I set the navigationBar to hidden I notice that it disappears before the next screen gets pushed and the slide animation happens (because I need a UIToolbar at the top).
So question #1: is there a way to push a new view controller and setting the navigationbar to hidden, and not getting the hide animation until after the new view controller is on screen. it looks funny that the navigation bar hides then pushes the new view controller.
Once the new view controller is present, when I pop it off, I set the navigation bar back
[self.navigationController.navigationBar setHidden:NO];
But when it is popped, the navigationbar is not back any more. Is it because this navigationBar is for the current navigationController and not the new one that is being presented after the pop? (question #2)
Question 3: Realizing it isn't showing my navigationBar, in the viewController that gets presented after the pop, in its viewDidAppear, I added
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigationController.navigationBar setHidden:NO];
}
which shows the navigationBar, but the view size is incorrect since it seems like once the navigation bar was hidden, the rest of the view took up the empty space, and then the navigationBar is on top of the content. Is there anything I can do about this? Or am I approaching it incorrectly with push and pop?(question #3).
Thanks!
I was running into the very same problem (only in reverse: I was starting from a NavigationBar being hidden and pushing a view where I wanted the NavigationBar visible), and there's actually an extremely easy fix.
Simply replace your calls:
[self.navigationController.navigationBar setHidden:NO];
with
[[self navigationController] setNavigationBarHidden:NO animated:YES];
In my code, I call these statements in the - (void)viewWillAppear:(BOOL)animated methods of each respective View Controller.
I just tried this solution in the order you are using (visible, then hidden), and it seems to work just as well.
Interesting issue. You could try changing the hidden property in viewWillAppear and viewWillDisappear, but it seems like that might not give the desired results either.
Can you present the view controller modally instead of making the navigation bar disappear? If it's the last view controller on the stack, that would be possible. It might also make more sense to the user to see a view controller presented differently. This might indicate to the user that navigating away from this view controller is no longer done with the Back Button. It could be more reasonable than having the navigation bar just disappear.
If you still wanted the view controller to slide in from the right, I don't think it can be done with a modal view controller. But, you could do that by animating a view that fills the screen. (You just add the view with a frame that has origin.x equal to the width of the screen. Then, in the animation, you change origin.x to 0.0. Let me know if you need more detail on this.)
However, I would recommend presenting the view controller in a different manner from the way a view is generally presented by a navigation controller. Because, essentially, you are no longer letting the user navigate away from this view as he/she generally would from within a navigation controller. (So, my response to question #3 would be 'yes'.)

Getting empty view and blank navigation bar when I use popViewControllerAnimated

I'm writing an iPhone app that is based on a UINavigationController. I'm pulling data from a server that sometime returns bogus links. I open each link by pushing a webview viewcontroller. I want to be able to include some error handling. I know if the link is no good. So I want to be able to pop the webview view controller as soon as I know that my webview has encountered an error.
Currently, I've tried using the following code:
[self.navigationController popViewControllerAnimated:YES];
I then get a Navigation bar with nothing displayed in it, but if I click where the "back" button should be it operates appropriately. The title pops up when I click where the "back" button should be. The view where the viewcontrollers usually display there content is blank white too even though I'm popping back to a UITableViewController.
I've tried this as a workaround:
UINavigationController *nav = self.navigationController;
[self.navigationController popViewControllerAnimated:YES];
[nav.visibleViewController.view setNeedsDisplay];
I've checked the viewControllers array in the UINavigationController and it has the right viewcontrollers in it (ie it has removed the viewcontroller for the webview).
I also tried putting code in the viewWillAppear of the viewcontroller I'm popping back to, but the method is never getting called.
I'm looking for a way to force the UINavigationController to reload the same way that you can call reloadData on a UITableView.
Any help would be greatly appreciated.
I saw something like this on my app where I was using a navigation bar I added in Interface Builder on the root view of a navigation controller and then programmatically creating the nav bar and its subviews for the second view. When I would pop the second view to return to the first view I would hide the self.navigationcontroller bar which would show the white space underneath until the IB nav bar of the previous view appeared. To fix this I decided to stick with programmatically creating all my navbars which fixed the issue for me.
TL;DR - if you are using both IB and programmatically made navbars this can happen when popping views, stick with one or the other for all the navbars yo

Three20 navigation by openURLAction; self.navigationController is nil in pushed VC?

The navigation commences with [[TTNavigator navigator] openURLAction:theUrl]; from one UIviewController controller and another UIViewController is the target of that URL. The map is set with set with the following code and there is no doubt navigation goes to the right place:
TTURLMap* map = navigator.URLMap;
[map from:#"tt://goToMyViewController" toViewController:[MyViewControllerClass class]];
In the pushed view controller i want to manipulate the image on the Back button but don't want to change the title. It should always be the title of the view controller this one was pushed on top of, or localized "Back" if no title was set.
Problem:
In this pushed view controller's viewDidLoad I'm starting with
NSArray* viewControllers = self.navigationController.viewControllers;
to get the navigation stack so I can look at the title of the appropriate view controller. But viewControllers is nil...
However if I do nothing the default back button does have the correct title. I thought of looking at the leftBarButtonItem and backBarButtonItem title properties but there is nothing meaningful there either...
Anyone know what is going on, why this is happening or how it can be worked around?
This is one of those things where viewDidLoad is the wrong place to do it - after comparing various view controllers and finding no real difference in how they were invoked (yet had nil viewControllers while others didn't) it struck me that if it was really nil, popViewControllerAnimated shouldn't work either. I found viewControllers was NOT nil where I was calling popViewControllerAnimated and from there experiment showed I could get the title I was after in viewWillAppear:.
So, viewWillAppear: seems to be a reliable place to touch self.navigationController while viewDidLoad is not.