In my application I'm using a Navigation Controller to push one view that loads a Tab Bar Controller and a custom Navigation Bar as well. The problem is that the Tab Bar disappears below the bottom of the screen, and I don't know what's causing the problem.
If I load a simple Tab Bar in the next view, it positions itself correctly... but what I need is a Tab Bar Controller, and in that case the Tab Bar disappears below the bottom. I have tried changing the view and size properties of the Tab Bar, but that did not solve the problem.
I also realised that the images and text of the tabs don't show (I have set up the "favourites" and "contacts" images and text, and they are big enough and should be visible on the top side of the tab, but they are not).
Both tabs work perfectly, by the way.
There is an image here.
I load the Tab Bar with the following code:
- (void)viewDidLoad {
[super viewDidLoad];
myTabBarController = [[UITabBarController alloc] init];
SettingsViewController* tab1 = [[SettingsViewController alloc] init];
AboutViewController* tab2 = [[AboutViewController alloc] init];
NSArray* controllers = [NSArray arrayWithObjects:tab1, tab2, nil];
myTabBarController.viewControllers = controllers;
[self.view insertSubview:myTabBarController.view belowSubview:myNavigationBar];
}
It doesn't matter if I remove the Navigation Bar or not. I have tested using this instead:
[self.view addSubview:myTabBarController.view];
... forgetting about the Navigation Bar, but the Tab Bar still goes under the bottom.
I don't know if the problem is in one of my NIB files or in how I load the view (although I do this as I read in the Apple's SDK documentation). Any ideas?
Another question would be... do you know how could I change the title of my Navigation Bar when I select the second tab? I imagine I would have to do it in viewDidLoad in AboutViewController.m, would that be correct?
Thanks for you time!
Please ask one question per submission - it will allow us to better help you.
For your first problem: you need to add the tab bar controller to the navigation controller, not to that view. The heirarchy should be:
Navigation Controller
Tab Bar Controller
Your View(s)
(Though Apple's documentation suggests that the tab bar should be application-wide and should thus be the root view, not the navigation controller).
For your second question, the text on the "Back" button is determined by the title property of the previous view controller. To change it, do the following (source):
- ( void )viewDidLoad
{
[ super viewDidLoad ];
UIBarButtonItem *backButton =
[[ UIBarButtonItem alloc ] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:nil
action:nil ];
self.navigationItem.backBarButtonItem = backButton;
[ backButton release ];
}
EDIT: It appears you want to set the title of the second view controller in your navigation stack. That's easy:
- ( void )viewDidLoad
{
[ super viewDidLoad ];
self.title = #"Title";
}
Related
I apologize I am new to iphone programming.
I have created a Master-Detail Iphone application (so Navigation Controller came with the project). I segue to a new view controller I created through a UIBarButtonItem on the masterviewcontroller. However unlike the detailviewcontroller (that came with the project) I can not seem to get the navigationitem (or navigationbar?) to display on the view even though it appears in the scene list of my storyboard.
Heres some code and a screenshot:
In my masterviewcontroller.m viewdidload() function
UIBarButtonItem *settingsButton = [[UIBarButtonItem alloc] initWithTitle:#"Settings" style:normal target:self action:#selector(goToSettings:)];
self.navigationItem.leftBarButtonItem = settingsButton;
in my masterviewcontroller.m
- (IBAction)goToSettings:(id)sender{
[self performSegueWithIdentifier:#"SettingsSegue" sender:self];
}
I tried adding a title to the navigationitem during the viewDidLoad function of the new viewcontroller.m class i created (mentioned in this Link but it didn't work)
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.title = #"Settings";
self.navigationItem.leftBarButtonItem = self.editButtonItem;
}
But it still shows up in my storyboard ( it shows up in the list under the scene but not in the display of the view)
So my question is why is it now showing up and how do I get it to? I want a back button like my detail view controller that came with the master-detail project.
EDIT#1
I have added a check for whether navigation controller is nil and it is not nil (the if statement is never entered) I also tried changing the navigation item to back and removing and none has worked.
if(self.navigationItem == nil)
{
[ self.navigationItem init];
}
self.navigationItem.title = #"Settings";
self.navigationItem.leftBarButtonItem = self.navigationItem.backBarButtonItem;
Now that I have enough reputation to show an image I can show that the navigation item shows up in the list but doesnt show up on the view
The Navigation item did not show up because of the "style" of my segue.
The segue that moved the scene from the master view controller to the settings view controller was set to 'modal'. It has to be set to 'push'. This is done from the storyboard on the utilities pane
You have to change your Segue Style by doing this:
Select the Segue in your Storyboard;
Go to the Attributes inspector (on the right pane tabs);
Change the Style attribute to Push.
It will make the screen roll from right to left and the Navigation bar will appear sliding.
With Modal, the screen come from bottom to the top of the screen and it will not let the Navigation bar appears.
The problem in my case was that the Navigation controller wasn't the "initial View Controller"
So I had to do this
You have verified that your navigation controller listed in the viewDidLoad method is not nil?
Assuming that you do correctly have a self.navigationItem that is non-nil, it appears that you are incorrectly setting your self.navigationItem.leftBarButtonItem to an editButtonItem, instead try removing this all together!
If removing it does not solve the problem try:
self.navigationItem.leftBarButtonItem = self.navigationItem.backBarButtonItem;
Please check if your view controller is the root view controller of the navigation controller. You cant directly present a view controller as a modal view controller. You have to make your view controller as the root view controller of a navigation controller and then present your navigation controller as the modal view controller.
// Create the root view controller for the navigation controller
// The new view controller configures a Cancel and Done button for the
// navigation bar.
YourViewController *addController = [[YourViewController alloc]
init];
// Configure the YourViewController.
// Create the navigation controller and present it.
UINavigationController *navigationController = [[UINavigationController alloc]
initWithRootViewController:addController];
[self presentViewController:navigationController animated:YES completion: nil];
You need to have a Navigation Controller and a View Controller.
"The navigation controller manages the navigation bar at the top of the interface and an optional toolbar at the bottom of the interface. The navigation bar is always present and is managed by the navigation controller itself, which updates the navigation bar using the content provided by its child view controllers. When the isToolbarHidden property is false, the navigation controller similarly updates the toolbar with contents provided by the topmost view controller."
https://developer.apple.com/documentation/uikit/uinavigationcontroller
The Navigation Item also appears in the View Controller Scene you can look for it there and edit it too
I am using UISplitViewController with UITabbarController as master view and navigation controller as detail view. Each of the tabs on the master view contain a navigation controller. When any of the tabs on the master view are selected, a view is pushed on the detail view navigation controller.
recentsviewController = [[RecentsViewController_ipad alloc]initWithNibName:#"RootViewController" bundle:nil];
recentsNav = [[UINavigationController alloc] initWithRootViewController:recentsviewController];
//similarly rootNav and favNav
NSArray* controllers = [NSArray arrayWithObjects:recentsNav,self.rootNav,favNav,nil];
self.tabbarController.viewControllers = controllers;
detailViewController=[[LoginViewController_ipad alloc]init];
detailNav=[[UINavigationController alloc]initWithRootViewController:detailViewController];
splitViewController =[[UISplitViewController alloc]init];
splitViewController.viewControllers=[NSArray arrayWithObjects:self.tabbarController,self.detailNav,nil];
splitViewController.delegate = self.detailViewController;
[self.window addSubview:splitViewController.view];
[self.window makeKeyAndVisible];
This seems to work fine. When app goes into portrait mode a 'Browse' button is added to the navigation bar. Clicking this button shows the hidden view along with the tabs perfectly fine. I can switch between the tabs and work on the views displayed in the popover. When tapped on other than popover area the popover is dismissed as expected.
The two things that are not working are
The popover has to show up on its own each time app switches to portrait mode without the user having to select the button added to nav bar
On some occasions I need to dismiss the popover programatically.
I have tried foll code :
- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {
barButtonItem.title = #"Browse";
[[self navigationItem] setLeftBarButtonItem:barButtonItem];
self.appDelegate.rootPopoverButtonItem = barButtonItem;
self.appDelegate.splitViewPopover = pc;
[self.appDelegate.splitViewPopover presentPopoverFromBarButtonItem:self.appDelegate.rootPopoverButtonItem permittedArrowDirections:UIPopoverArrowDirectionUp animated:NO];
}
This adds a black translucent popover each time the orientation changes. How do I make it show what the browse button shows when it is clicked?
The usual dismissPopvoerAnimated does not seem to work here.
Any help is appreciated.
Using performSelector:withObject:afterDelay: fixed the issue
Im having a strange bug in my code while working on an app for iphone. I am creating a navigation controller and putting it within my tab bar controller and then when i move from my initial screen to a secondary screen the back button on the secondary screen points to itself. so when back is pressed it just reloads itself and then the next time it is pressed it goes back to the first screen.
UINavigationController *nav1 = [[UINavigationController alloc] init];
// create the initial views for each nav controller
SearchViewController *searchView = [[SearchViewController alloc] init];
searchView.title = #"Search";
//place all the viewcontrollers on the nav controllers ready to view
[nav1 pushViewController: searchView animated:NO];
//create tab bar out of above nav controllers
UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:#"Search" image:[UIImage imageNamed:#"search.png"] tag:0];
nav1.tabBarItem = item;
UITabBarController *tbc = [[UITabBarController alloc] init];
tbc.viewControllers = [NSArray arrayWithObjects:nav1, nil];
//
[nav1 release];
above code is in appdelegate for initial set up of nav + tab controller
SecondScreenViewController *sVC = [[SecondScreenViewController alloc] init];
sVC.title = #"Screen 2";
[self.navigationController pushViewController:sVC animated:YES];
[sVC release];
above is the code in the search view controller that loads the second screen / viewcontroller to the nav controller. But the back button at the top of screen 2 has the word screen 2 in it and when i press it once it reloads itself and then the back button says search (which is the title of first screen) . this time pressing it brings it back to the first screen.
Im just confused why the back button displays the view controllers own title name and reloads itself. I dont have any other code in these screens really, they are just blank screens with labels displaying which screen is there while i learn how to use it correctly
In the Apple Docs for UINavigationController for the designated initializer
- (id)initWithRootViewController:(UIViewController *)rootViewController
it is stated that:
Every navigation stack must have at least one view controller to act as the root.
I would recommend trying to initialize your UINavigationController with a rootViewController.
TiltedWindmill, I've experienced that problem before. In my case, in my head, I wanted to do this:
( > = pushing view controller )
Start at MapViewController > Details About An Attraction for a clicked pin on the map > MapViewController > Then pushing another DetailsViewController.
In my MapViewController, this view controller was registered for a notification. Theoretically, I thought I was navigating like this Map > Details View Controller > Map > Details View Controller. The thing was, whenever I tapped on the pin on the map, the Notification was fired and both copies of MapViewController that was on the navigation stack responded to the notification.
As a result it pushed two copies of the same DetailsViewController. So the real navigation was like this:
Map > Details View Controller > Map > Details View Controller copy1 + DetailsViewController copy2
*> = Second details view controller was pushed ontop of the previous one but not visible to the eye.
When I went to press the back button, it popped DetailsViewController copy2 and showed the same view controller (DetailsViewController copy1).
I fixed it by telling my MapViewController to unsubscribe from the notification on the event viewDidDisappear.
Not sure if you understood that :P
When I try to present a modalViewController, it covers up my navigation controller's navigation bar. Any tips? Thanks.
UPDATE (with code):
ComposeText *compText = [[ComposeText alloc] initWithNibName:#"ComposeText" bundle:[NSBundle mainBundle]];
compNavController = [[UINavigationController alloc] initWithRootViewController:compText];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:compNavController action:#selector(compDoneTapped:)];
compNavController.navigationItem.rightBarButtonItem = doneButton;
[self presentModalViewController:compNavController animated:YES];
compText.title = #"Compose";
[doneButton release];
Everything seems to be in order, but the button is still not appearing on the navigation bar.
That's what it is supposed to do. If you want a navigation bar, present a new UINavigationController modally and set it's root view controller to your modalViewController.
The question you need to ask yourself is: "why do I want to show my navigationbar". If it is to give the user access to some buttons then it is the wrong reason. Modal view controllers are there to take full control of the screen and to not allow the user to manipulate anything else in the app until the controller is dismissed. If you don't want that do as Cyprian suggests and push a viewcontroller on your navigation stack.
If it is just a visual thing (logo ...) duplicate it in your modal view controller.
UINavigationController has it's own method to show another viewController.
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
It uses stack, to push new viewController so it can handle its navigation with buttons.
So, I want my app starts with a UIViewController(without seeing a tabbar), and then enter a UITableView with navigationbar and tabbar. the problem is that the Tabbar is visible at the app starts up, anyone can help on this will be very appreciated...
I think you should either send -presentModalViewController:animated: to your main UIViewController with the tab bar controller as an argument or just do this:
[myWindow addSubview: myTabBarController.view];
Make your app a navigation based application (rather than a tab bar based one) then add a tab bar on the UITableView.
There is help for adding the UITabBar here
I do it like this : in this case drawing a table view and map view (From the Locati application)
tabBarController = [[UITabBarController alloc] init]; // creates your tab bar so you can add everything else to it
searchTableViewController = [[SearchTableViewController alloc] init]; // creates your table view - this should be a UIViewController with a table view in it, or UITableViewController
UINavigationController *searchTableNavController = [[[UINavigationController alloc] initWithRootViewController:searchTableViewController] autorelease];
[searchTableViewController release]; // creates your table view's navigation controller, then adds the view controller you made. Note I then let go of the view controller as the navigation controller now holds onto it
searchMapViewController = [[SearchMapViewController alloc] init];
UINavigationController *mapTableNavController = [[[UINavigationController alloc] initWithRootViewController:searchMapViewController] autorelease];
[searchMapViewController release]; // does exactly the same as the first round, but for your second tab at the bottom of the bar.
tabBarController.viewControllers = [NSArray arrayWithObjects:searchTableNavController, mapTableNavController, nil]; //add both of your navigation controllers to the tab bar. You can put as many controllers on as you like
I found this pattern a long time ago. Sorry that I can't point at the original.
YOu then need to add the tabbarcontoller to the relevant view ([...view addSubView:tabBarController];) possibly setting frame first.