I would like to add a TabBar to an existing view-based application I already started just to allow the user to switch to other parts of the app like the "About" section and another section entitled "Saved Searches" to display a navigational content (saved searches list > specific search result > product details).
Any idea on how to do this ? All tutorials I found point me directly to a TabBar template.
Thx for helping,
Stephane
You could start off with the UITabBar Application Template and you'll realize it's very easy to do:
In your UIApplicationDelegate class, in the method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Instantiate a UITabBarController like this:
UITabBarController *tabBar = [[UITabBarController alloc] init];
Then you set the view Controllers that will appear on the tab bar:
tabBar.viewControllers = viewControllers;
Which is a NSArray you can previously create with your UIViewController subclasses:
NSArray *viewControllers = [[[NSArray alloc] initWithObjects:vc1, vc2, vc3, nil] autorelease];
After this, you only have to set it as the root view controller of the window, or add it as a subview (it has the same effect, but the first approach doesnt work prior to iOS 4)
self.window.rootViewController = tabBar;
or
[self.window addSubView:tabBar.view];
And then
[tabBar release];
To achieve the kind of navigation that you say in your question, the view controllers you set to the tabBar should be instances of UINavigationController, which are very easy to create like this:
UINavigationController *vc1 = [[UINavigationController alloc] initWithRootViewController:firstViewControllerPage];
And inside them, you can push (navigate to) other view controllers doing:
[self.navigationController pushNavigationController:anotherViewController animated:YES];
Hope this brief review of it makes it a bit clear :)
You can create a new UITabBarController, and add it's view as a subview of your applications window. Then, add your other view controllers (for your "About" and "Saved Searches" sections) to that tab bar controller.
This can be done most easily in Interface Builder. In your MainWindow.xib, drag a Tab Bar Controller object onto the canvas. This will automatically create a tab bar with two items (one for each of the view controllers added). For each view controller under the tab bar controller, go to the identity inspector and change its class to your custom view controller subclass. Then, show the attributes inspector and there is a field "NIB Name" - again, set this to the appropriate nib name. Your custom controller views will then be loaded from their corresponding nib files. All that's left to do is name each tab in Interface Builder, and give it a graphic.
You can also do this programmatically if you don't like IB, by assigning the custom view controllers to the tab controller's viewControllers property, and assign a selectedViewController.
Hope this helps.
EDIT
Thought it might be helpful to show a little hierarchy! Your MainWindox.xib structure might look something like this:
AppDelegate
UIWindow
UITabBarController
UITabBar
AboutViewController (view loaded from "AboutViewController.xib")
Tab Bar Item - About
UINavigationController
Navigation Bar
SavedSearchesViewController - Root View Controller (view loaded from "SavedSearchesViewController.xib"
Tab Bar Item
And push appropriate view controllers from SavedSearchesViewController as normal to provide navigation content.
How can I use Tab Bar in my View Based application in second view ?
EDIT :
(Suppose)My application contains four views. The navigation from firstView to secondView is simple , I want the Tab Bar on the secondView and connect rest of the two view with the Tab Bar.
On the other hand I think this has been discussed here: uitabbarcontroller / uitabbar in navigation based project
Just take a look.
EDIT: If it is a navigation based app and you want your tabbar on the second view, just initialize the navigation controller and use pushViewController message to it and push the tabBarController onto the navigation stack.
tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1,viewController2,nil];
[self.navigationController pushViewController:tabBarController animated:YES];
Place this wherever you wish to push this tabBarController from the first view, where the first view is a navigation controller based entity and viewController1,viewController2 etc are the view controllers from the tab bar items.
I have a simple tabBarController application where the user can navigate around 3 views.
In one of the views I have a UIButton that when touched moves the user to a fourth view. the problem is that the new view doesn't have the tab bar navigation visible.
what do I need to do to the fourth view to have it also use the tabBarController feature set.
thanks for any help
here's the code that transitions to the fourth view when a UIButton is touched:
-(IBAction) nextQuestion {
Question2 *q2 = [[Question2 alloc] initWithNibName:#"Question2" bundle:nil];
q2.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:q2 animated:YES];
[q2 release];
}
A modal view controller always takes up the entire screen. Its purpose is to provide a modal interface that does not let the user interact with other parts of the UI until they dismiss the modal view.
To display another view inside a tab, you could make the root controller of that tab a navigation controller. A button tap would then push the Question 2 controller on the nav controller's stack.
My app is a tab bar application, which one of the tabs is a TableViewController instead of a viewController which works fine (the table displays great) but where and how do I add UINavigationController to it? :-)
You can do this 2 different ways... in IB or code. If I'm dealing with a TabBar I usually do it in IB. All you have to do there is is drag a NavigationController object where your tableview object currently sits... then just make your tableviewcontroller the first child of your new navigation object.
TabBarController
-(Tab Bar)
-NavigationController
--(Navigation Item)
--TableViewController
or
If you want to do it in code... I would just set it up within your app delegate (usually because a tab bar is at the highest point in your app... meaning it appears right away after loading):
// Create a tabbar controller and an array to contain the view controllers
tabBarController = [[UITabBarController alloc] init];
NSMutableArray *localViewControllersArray = [[NSMutableArray alloc] initWithCapacity:numberOfTabs];
// setup the view controllers
UINavigationController *myNavigationController;
myNavigationController = [[UINavigationController alloc] initWithRootViewController:myTableViewController];
// add to tab bar controller
[localViewControllersArray addObject:myNavigationController];
tabBarController.viewControllers = localViewControllersArray;
// add the tab bar to the window
[window addSubview:tabBarController.view];
You should then release the objects you just created since they will be retained by the TabBarController and Navigation Controller. Hope this helps
As Ryan noticed you can make it easily using IB. Here is how you can achieve this:
Launch Xcode and create new Tab Bar Application project.
Under resources group find MainWindow.xib and double click it to open in Interface Builder.
Next, select Tab Bar Controller object and open Inspector window (Command + Shift + I).
Notice "View Controllers" section in Inspector () then click on View Controller popup and change value from View Controller to Navigation Controller.
That's it! Now you can use your UITableViewController subclass inside this UINavigationController.
I'm trying to implement a UI structured like in the Tweetie app, which behaves as so: the top-level view controller seems to be a navigation controller, whose root view is an "Accounts" table view. If you click on any account, it goes to the second level, which has a tab bar across the bottom. Each tab item shows a different list and lets you drill down further (the subsequent levels don't show the tab bar).
So, this seems like the implementation hierarchy is:
UINavigationController
Accounts: UITableViewController
UITabBarController
Tweets: UITableViewController
Detail view of a tweet/user/etc
Replies: UITableViewController
...
This seems to work[^1], but appears to be unsupported according to the SDK documentation for -pushViewController:animated: (emphasis added):
viewController: The view controller that is pushed onto the stack. It cannot be an instance of tab bar controller.
I would like to avoid private APIs and the like, but I'm not sure why this usage is explicitly prohibited even when it seems to work fine. Anyone know the reason?
I've thought about putting the tab bar controller as the main controller, with each of the tabs containing separate navigation controllers. The problem with this is that each nav controller needs to share a single root view controller (namely the "Accounts" table in Tweetie) -- this doesn't seem to work: pushing the table controller to a second nav controller seems to remove it from the first. Not to mention all the book-keeping when selecting a different account would probably be a pain.
How should I implement this the Right Way?
[^1]: The tab bar controller needs to be subclassed so that the tab bar controller's navigation item at that level stays in sync with the selected tab's navigation item, and the individual tab's table controller's need to push their respective detail views to self.tabBarController.navigationController instead of self.navigationController.
The two previous answers got it right - I don't use UITabBarController in Tweetie. It's pretty easy to write a custom XXTabBarController (plain subclass of UIViewController) that is happy to get pushed onto a nav controller stack, but still lives by the "view controller" philosophy. Each "tab" on the account-specific view (Tweets/Replies/Messages) is its own view controller, and as far as they are concerned they're getting swapped around on screen by a plain-ol UITabBarController.
I'm building an app that uses a similar navigation framework to Tweetie. I've written a post about how to do this on my blog www.wiredbob.com which also links to the source code. It's a full template you could take and use as a basis for another project. Good luck!
It's possible to add a UITabBar to any UIViewController. That way you don't actually have to push a UITabBarController and therefore stay within the guidelines of the Apple API.
In interface builder UITabBar is under "Windows, Views & Bars" in the Cocoa Touch Library.
I do this in a couple of my apps. The trick to adding a tab bar to a navigationController based app is to NOT use a TabBarController. Add a Tab Bar to the view, make the view controller for that view a TabBarDelegate, and respond to user selections on the tab bar in the code of the view controller.
I use Tab Bars to add additional views to the Tab Bar's view as sub-views, to reload a table view with different datasets, to reload a UIPickerView, etc.
I was struggling for the past hour to implement a UITabBar because it would get hidden when I tried to display my view; then I found this post:
Basically, make sure you insert your new view below the tabbar, per this line of code:
[self.view insertSubview:tab2ViewController.view belowSubview:myTabBar];
In my app, the root view controller is a UINavigation controller. At a certain point in the app, I need to display a UITabBar. I tried implementing a UITabBar on a UIView within the navigation hierarchy, as some of the previous posts suggested, and this does work. But I found that I wanted more of the default behavior that the tab controller provides and I found a way to use the UITabBarController with the UINavigation controller:
1) When I want to display the UITabBarController's view, I do this:
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = myUiTabBarControllerInstance;
2) When I want to return to where I was in the navigation hierarchy, I do this:
appDelegate.window.rootViewController = myNavControllerInstance;
This could be achieved by simply embedding the TabBarController in the Navigation Controller.
In the storyboard:
Drag a ViewController
Click on the ViewController's Scene
Click on editor >> Embed in >> Navigation Controller.
Drag a button on the same ViewController.
Drag a TabBarController
Connect the button on the ViewController to the TabBarController via push Segue Action.
In this case only the TabBarController's RootViewController would be in the Navigation Controller's stack. All The TabBarItems would have the Navigation Bar at the top and user can go to Home Screen at any time, irrespective of the selected TabBarItem
This could be done at any ViewController in the Navigation Controller's stack.
If it works, please suggest me how to increase the reputation so that I can post the images and the code in the next answer. :)
This is how i did it. This is actually pushing a tabbarcontroller onto navigation controller. It works fine. I didn't find anywhere in the documentation that apple doesn't support this way. Can someone give me link to this warning?
If this is truth, is it possible that apple refuses to publish my app to appstore?
-(void)setArrayAndPushNextController
{
MyFirstViewController *myFirstViewController = [[MyFirstViewController alloc] init];
MySecondViewController *mySecondViewController = [[MySecondViewController alloc] init];
myFirstViewController.array = self.array;
NSArray *array = [[NSArray alloc] initWithObjects:myFirstViewController, mySecondViewController, nil];
UITabBarController *tab = [[UITabBarController alloc] init];
tab.viewControllers = array;
[array release];
UITabBarItem *item1 = [[UITabBarItem alloc] initWithTitle:#"first title" image:nil tag:1];
UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:#"second title" image:nil tag:2];
myFirstViewController.tabBarItem = item1;
mySecondViewController.tabBarItem = item2;
[self stopAnimatingSpinner];
[self.navigationController pushViewController:tab animated:YES];
[tab release];
[item1 release];
[item2 release];
}
I wrote a blog post on how I approached this problem. For me, using a modal view was a simpler solution than writing a custom tab-bar implementation.
http://www.alexmedearis.com/uitabbarcontroller-inside-a-uinavigationcontroller/