I have an application that has a UITabBarController created in IB. That tbc loads 3 views which work fine up to now.
I decided to INSERT a UINavController as the starting VC and have a UITableViewController display 4 menu items in cells. Each of the 4 items will in essence load the UITabBarController put pass in a different xml file to process in order to display data in those 3 tabs.
I essentially did this at the end of the applicationDidFinishLoading:
MainMenu *rootViewController = [[MainMenu alloc] init];
navController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = navController;
[window makeKeyAndVisible];
return YES;
I then created the MainMenu as the rootViewController subclassing UITableViewController and added a hardcoded array for now which displays the 4 items I want. I had the didSelectRowAtIndexPath run this code:
tabBarController = [[UITabBarController alloc] init];
[self.navigationController pushViewController:tabBarController animated:YES];
[tabBarController release];
It turns out that when I run it, the navcontroller pushes the tab controller but only the first tab shows up. Here is a pic.
You should never push a UITabBarController from a UINavigationController. Apple clearly says this:
An app that uses a tab bar controller can also use navigation controllers in one or more tabs. When combining these two types of view controller in the same user interface, the tab bar controller always acts as the wrapper for the navigation controllers.`
That essentially means tab bar should be the parent of all other view controllers that get called. Not the other way round. You should probably change the way you present your app.
More information here.
Related
I have a tab bar controller with a button like so:
- (void) addButtonPressed:(UIButton *) sender
{
[sender setBackgroundColor:[UIColor regularColor]];
PostViewController *post = [[PostViewController alloc] init];
[self.navigationController pushViewController:post animated:YES];
}
This code runs but the PostViewController is never shown and the tab bar controller remains.
How do I get to push to a new controller?
The NavigationController was created and StartViewController was add as rootController.
Then in StartViewController I have:
TabBarController *tab = [[TabBarController alloc] init];
// Presentation
[self presentViewController:tab animated:NO completion:nil];
in tab bar you need to create separate Navigation Controllers.
Suppose there are 3 tabs A, B and C. All the three tabs have functionality of navigation from one view to another. than you need to create three separate Navigation controllers eact pointing to Tab A, B and C. In this way you can navigate to any class within the specific Tab.
Check out this link for more details.
Hope this will help you. Happy coding :)
You may need to embed your tab bar controller within a navigation controller, In your storyboard click on your tabbarController so that it is highlighted with all the blue lines and then go to Editor in Xcode choose embed IN> UINavigationController ..If you want to do it programatically then in your AppDelegate where you setup your Window just Use This::
UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:tabBarController];
navigationController.toolbarHidden=YES;
navigationController.navigationBarHidden=YES;
self.window.rootViewController =navigationController;
if you are using .xib then you have to use NSBundle to load nib
if you are using storyboard then you need to use prepareForSegue to pass on data or just display it out
I am creating an application that contains the Use of both Navigation Bar along with Tab bar. For Some screens in the App we are not showing the tab bar.
But most of the screens of the Applications are showing the Tab bar.
So my question is with which option i should start to create my Project?
i.e With the single view Application OR with Tab-based Application. Also out of 30 pages of the application only 5-6 pages are there that are not showing the Tab bar.
Apart from these all the screens are showing Tab bar.
So please suggest me an efficient and most useful way to start my project with. Also if i am creating my project with single view Application then how can i create an Tab bar with Navigation Bar with xib only. I don't want to use storyboard.
Also what if i start my application with Tab based and hide the tab bar for the pages that don't need to show.
Please someone suggest me.
If you need a Tab Bar Controller to be present then It should be added as your root view, I suggest start with your Tab Bar Controller and embed that in a Navigation controller
EDit---
If you want to load the viewCOntroller first then You may have to add that to your window in your appdelegate
ViewController *vc=[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
UINavigationController *nav=[[UINavigationController alloc]initWithRootViewController:vc];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
now when you want to show your tabBarCOntroller through button then in the buttons IBAction just do this…
-(IBAction)button:(id)sender{
UIApplication *appdelegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
ViewController *vc=[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
tabBarController= [[tabBarController alloc]init];
[tabBarController setViewControllers:#["your viewControllers"]];
UINavigationController * navigationController = [[UINavigationController alloc] initWithRootViewController:tabBarController];
appdelegate.window.rootViewController = navigationController;
[appdelegate.window makeKeyAndVisible];
}
So I'm trying to convert a single view application into a tabbed application. My use case is this - in one of the view controllers I want to push a new view controller and still have the tab underneath.
I'm currently doing this -
[self.tabBarController setViewControllers:#[self.searchViewController, self.loginViewController]];
[self.searchViewController presentViewController:self.searchViewController.detailController animated:YES completion:nil];
However, this makes the tab across the bottom disappear.
What should I do?
presentViewController is a "modal" presentation - the presented view controller takes over the entire screen. If you want to remain within the tab but move between view controllers, the root view controller in the tab should be a UINavigationController. You can then push/pop view controllers onto that.
There are two primary methods for view navigation, the first is a presentation which displays a view from the bottom that slides up, and the second is a push which displays a view from the right that slides in from the side.
In most cases, the view I am going to display and what action kicked off the navigation determine which method I will use. For example, if I have a table view that has a list of music albums and I want to search for a song by a particular artist, to see the songs within that album I want to PUSH the view controller, i.e. slide to the right. This gives me the built-in (and intuitive) ability to go back via the automatically added back button on the navigation bar in case the song I was looking for wasn't in the album I selected.
If perhaps I wanted to present the user with the ability to edit the album details, such as renaming the album, this is a totally different type of action, and I would want to PRESENT such a view modally, i.e. from the bottom.
The major distinction between the two is where are you going and what are you doing. If the next view you are going to show is something that does one action and you are then returned back to the original view, presenting modally from the bottom is conventional. If you are doing to be potentially navigation further and further into subsections and will be coming back and forth between said subsections, like Artist->Album->Song etc., you are going to want to push the view from the side, just like the default music app in iOS does.
This is an example starter project I created that demonstrates an easy way to make this work the way you likely want. I create instances of the different view controllers I want to be contained in the tabBarController, which are associated with the tabs, and then "wrap" them each with their own navigation controller before adding them to the tabBar via the .items property. This way each view controller has its own navigation hierarchy and within each you'll be able to call [self.navigationController pushViewController:] or [self.navigationController presentViewController] to keep the navigation 'within' the views and separate from the tabBar itself.
#import "AppDelegate.h"
#import "TabBarViewController.h"
#import "InfoViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
InfoViewController *firstVC = [[InfoViewController alloc] init];
firstVC.title = #"First";
firstVC.view.backgroundColor = [UIColor redColor];
UINavigationController *firstNC = [[UINavigationController alloc] initWithRootViewController:firstVC];
InfoViewController *secondVC = [[InfoViewController alloc] init];
secondVC.title = #"Second";
secondVC.view.backgroundColor = [UIColor blueColor];
UINavigationController *secondNC = [[UINavigationController alloc] initWithRootViewController:secondVC];
TabBarViewController *tabBarVC = [[TabBarViewController alloc] init];
tabBarVC.viewControllers = #[firstNC, secondNC];
self.window.rootViewController = tabBarVC;
[self.window makeKeyAndVisible];
return YES;
}
That resulted in the following:
Hope that helps!
I have been seeing this issue and resolving it by manually creating UINavigationController in the code. Could someone please tell me when I add Navigation Bar from XIB's Attribute Inspector -> Set Top bar to Black Navigation bar, it gets displayed in the XIB but when I run the program, it doesn't appear! I noticed that self.NavigationController was coming nil so I added UINavigationController in my XIB and assign NIB but still it's nil! What's wrong with this? Do I need any additional settings?
[EDIT1]
I tried adding it like below and it works but I want parent class to forward rotation and appearance events to child controller automatically. If I do following it won't send them because I am adding nvc as child and not marketsListViewController. So I thought I have to subclass UINavigationController. See EDIT2.
self.marketsListViewController = [[MarketsListViewController alloc] initWithNibName:#"MarketsListViewController" bundle:nil];
UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:self.marketsListViewController];
nvc.navigationBar.barStyle = UIBarStyleBlack;
[self.marketsListView addSubview:nvc.view];
[self addChildViewController:nvc];
[nvc didMoveToParentViewController:self];
[EDIT2]
I have subclassed marketsListViewController to UINavigationController and thought following will work but it doesn't. It just displays navigation bar, UITableView doesn't get displayed!
self.marketsListViewController = [[MarketsListViewController alloc] initWithNibName:#"MarketsListViewController" bundle:nil];
self.marketsListViewController.navigationBar.barStyle = UIBarStyleBlack;
[self.marketsListView addSubview:self.marketsListViewController.view];
[self addChildViewController:self.marketsListViewController];
[self.marketsListViewController didMoveToParentViewController:self];
[EDIT3]
I was wrong in Edit1 that children controller won't get rotation events when I add child as navigation controller's root controller. Parent still sends all the events automatically and that's what I want! :)
Could someone please tell me when I add Navigation Bar from XIB's
Attribute Inspector -> Set Top bar to Black Navigation bar, it gets
displayed in the XIB but when I run the program, it doesn't appear!
What you see in you .xib file is just there to help you get your layout right and get a good idea of what it'll look like. When you have an app that uses a navigation bar, the bar is almost always managed by a navigation view controller (UINavigationController). The view controllers that the navigation controller hosts don't worry about the nav bar -- their view hierarchies go in the space beneath the bar.
So, the right way to get a navigation bar in your app is almost certainly to use a navigation controller. If you only have one view controller, make that that the navigation controller's root view controller (note: the root view controller of the window will be the navigation view controller). You can change the appearance of the bar from your view controller by setting the navigation bar's style:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
Update: In the code you posted, you're just creating a new navigation controller, but not doing anything with it. I alluded above the the fact that (in most cases) the navigation controller should be the window's root view controller. It's fine to create your navigation controller in code, but you'll usually do it in the app delegate, and once you create it you'll set it as the window's root view controller. Here's an example borrowed from a project made fresh from Xcode's master/detail template (sans storyboards):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MMMasterViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
Note that after creating the window and the navigation controller, the code sets the nav controller as the window's root view controller.
Design requirement:
Show a list of items the user can pick from
After having picked an item, bring the user to a new view with a back button. The new view should contain a list of tabs at the bottom that are not present in the first screen
When clicking an item in the tabs, a new screen should appear with a back button and the tabs should still be visible at the bottom.
Clicking a tab should take the user back up the hierarchy to #2. Not to the first screen.
I have tried following structure:
UINavigationController
UIViewController with a UITableView
UIViewController with a UITabBar (like here http://www.wiredbob.com/2009/04/iphone-tweetie-style-navigation.html)
and also
UINavigationController
UIViewController with a UITableView
UITabbarController
Both cases work fine with displaying the UITabBar, but when I click an item in one of the tabs and push a new UIViewController, then the tabs at the bottom disappears. I want the tabs to remain in place for all pushed UIViewControllers that occurs inside a tab of the UITabBarController.
A related question is this one but it doesn't deal with the problem of pushed viewcontrollers inside a tab:
Tab bar controller inside a navigation controller, or sharing a navigation root view
Do I need to change the rootcontroller to the UITabController? Anyone actually implemented this?
Here is the correct structure:
UITabBarcontroller (UIWindow's rootViewController)
->UINavigationController (first tab)
-->UIViewController
->UINavigationController (second tab)
-->UIViewController
It sounds like you want to change the layout of your view hierarchy to accommodate your requirements. You should present your view controllers as such:
UITabBarController -> UINavigationController -> UIViewController
In your app delegate, you can implement this programmatically using something along the lines of:
UIViewController *viewControllerOne = [[[UIViewController alloc] init] autorelease];
UINavigationController *navigationControllerOne = [[[UINavigationController alloc] initWithRootViewController:viewControllerOne] autorelease];
UIViewController *viewControllerTwo = [[[UIViewController alloc] init] autorelease];
UINavigationController *navigationControllerTwo = [[[UINavigationController alloc] initWithRootViewController:viewControllerTwo] autorelease];
UITabBarController *tabBarController = [[[UITabBarController alloc] init] autorelease];
[tabBarController setViewControllers:[NSArray arrayWithObjects:navigationControllerOne, navigationControllerTwo, nil]];
[[self window] setRootViewController:tabBarController]
I haven't checked the above, it's just written from memory but should do what you require as an example.
Using this format, you can push any additional view controllers on to the navigation controller stack without your tab bar disappearing.
If you want to push this view hierarchy without having the tab bar controller as your root view controller, simply push the tab bar controller instead of setting it as the root view controller in the app delegate.
Hope that helps!