I need to present a modal tab bar controller using interface builder. I'd like to be able to specify and design the tab bar controller in a InfoViewController.xib file, then present it from a variety of locations within the application using something like:
UIViewController *vc = [InfoViewController create];
[self presentModalViewController:vc animated:YES];
I don't know how to setup the interface builder file. I can drag in a tab bar view controller, but it is not displayed when the view controller is presented. How should I link up this tab bar controller with the file owner?
You're over thinking this. Just do exactly what you said you were going to do. Reusability is a good thing.
Interface Builder is for designing your views.
You choose how and when to present them (e.g. modally) inside your code.
I ended up defining the tab bar controller in each XIB it was being presented from (currently only one). Not the ideal situation, but could not figure out how to do it from an external reusable XIB.
Related
I got a tabbed application like this:
and already set up everything like it should look, but it won't function yet. I already googled my problem and they said you first need to set up a NavigationController with the table view as rootView and then the NavigationBar but I really couldn't figure it out. Hope someone of you can help me.
Based on your response to my comment on your question here is what you should be doing:
First off, in order to make it look like the settings app table, you will need to change the style of your UITableView to UITableViewStyleGrouped.
Your hierarchy will consist of the following:
The viewcontroller that is actually added into your UITabBarController viewControllers array(since I see you have a tabbar as your lowest level of navigation) should be an UINavigationController. The root viewcontroller of the navigation controller should be the uiviewcontroller subclass you made that contains your table view. (let's say it's called SettingsViewController)
SettingsViewController *settingsViewController = [[SettingsViewController alloc] init];
UINavigationController *settingsNavController = [[UINavigationController alloc] initWithRootViewController:settingsViewController];
You will probably need to create a different UIViewController subclass for each type of detail pane you're going to want (if they have different functionality).
In the didSelectRowAtIndexPath UITableViewDelegate function, you will create the appropriate detail viewcontroller and push it onto your navigation stack.
Let's say you have a volume settings view controller as an example. The following is the code you would have in the function I just mentioned. Keep in mind you also need to actually check the index and/or section of the selected row to figure out which detail view should be shown.
VolumeSettingsViewController *volumeSettings = [[VolumeSettingsViewController alloc] init];
[self.navigationController pushViewController:volumeSettings animated:YES];
By default, this will function pretty much like the Apple Settings app navigation. The navigation bar will automatically have a "back" button to take you back to the settings view.
If you are using a Storyboard, select your view controller, go to the "Edit" menu and choose, "Embed in Navigation Controller."
If not using story boards, assuming this will be done in code, you need to create things in a reverse order of their hierarchy - something like this:
Create an instance of the Einstellungen tab's TableViewController using initWithNibName:
Create a UINavigationController using initWithRootViewController: and setting the Einstellungen as the root
Create a UITabBarController and set your navigation controller as one of the view controllers of this tab bar controller
Add the tab bar controller as a subview to the main window in your application delegate
This will create this hierarchy:
Tab bar controller
->view controller: Navigation Controller -> root view controller: Einstellungen
I'm trying to write an application that uses a navigation bar and tab bar in what (I'm gathering) is an unusual manner.
Basically, I've got several "pages" ("home", "settings", etc) that each have their own tab. I'd also like to have it so that the "home" page is the root view of the navigation bar, and the other pages are the second-level views of the navigation bar. That is, I should be able to navigate to any page by clicking the appropriate tab bar item, and should be able to navigate to the home page from any other page by clicking the navigation bar's back button.
Currently, I have a UINavigationBar (through a UINavigationController) and a UITabBar (through a UITabController) as children of a UIView. The various pages' view controllers are set as the tab controller's viewControllers property, and the home page's controller is also set as the navigation controller's root view. Each page view's tag is set to its index in the tab control. I have the following logic in the tab controller's didSelectViewController delegate method:
- (void) tabBarController:(UITabBarController*) tabBarController
didSelectViewController:(UIViewController*) viewController
{
if ([navController.viewControllers count] > 1)
[navController popViewControllerAnimated:NO];
[navController pushViewController:viewController animated:YES];
}
Also, in the navigation controller's didShowViewController delegate method, I have the following code:
- (void) navigationController:(UINavigationController *) navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
tabController.selectedIndex = viewController.view.tag;
}
The problem that's occurring is that when I run this, the navigation bar, tab bar and home page all display ok, but the tab bar will not respond to input - I cannot select a different tab.
I gather it's more usual to have the tab bar as the child of the navigation control, or vice versa. This doesn't seem to fit my approach, because I don't want to have to individually create the subordinate control each time a change occurs in the parent control - eg: recreate tab bar each time the navigation bar changes.
Does anyone have suggestions as to what's wrong and how to fix it? I'm probably missing something obvious, but whatever it is I can't seem to find it. Thanks!
EDIT: I'm guessing it has something to do with both controller's trying to have ownership of the page controller, but I can't for the life of me figure out a way around it.
Yikes. You're way out on a limb here. I've learned the hard way that UINavigationController and UITabBarController aren't very accommodating when you try to use them in nonstandard ways. UINavigationBar and UITabBar weren't designed to coexist as siblings in the view hierarchy. They really want to be distant cousins. Maybe the approach you're pursuing can be made to work somehow, but I personally wouldn't even attempt it.
With that said, I'll suggest one thing you can check, and then I'll tell you how I'd approach the problem.
Have you implemented, and are you returning YES from tabBarController:shouldSelectViewController: in your UITabBarControllerDelegate? If not, that would prevent your tabs from switching.
Assuming that won't solve all your problems, here's what I would do to get the behavior you're seeking:
Create a UITabBarController and set its view as the root view of your window.
Have a separate UINavigationController under each tab, each with its own navigation bar. (This is the standard way to use UINavigationController and UITabBarController together.)
Set a UITableViewController that displays an identical copy of your main menu table as the root view controller for each navigation controller.
When a row is selected on your "Home" view controller, switch to the associated content tab.
Set a delegate on your UITabBarController. In its tabBarController:didSelectViewController method, call pushViewController:animated:. This is similar to what you're currently doing, except you'll be calling it on (UINavigationController *)tabBarController.selectedViewController.
In the viewDidAppear:animated: of the root view controllers of your content tabs, switch to the "Home" tab. This way, when the user hits the back button to go back to "Home", it will switch to the right tab. (You may also need conditional code to prevent this from happening when the user first selects a content tab. I'm not sure.)
I'll be curious to know if Apple accepts this nonstandard behavior. Come back and let us know. Also, let us know if you get your approach working somehow.
I have created an UITabView application. Each view selected from the bar is a seperate controller with own nib file. I switch between them succesfully.
In the first view I have two buttons (check out the screenshot). When clicking them I want to switch to another views which are the parts of the current view controller. I use:
[self presentModalViewController:anotherViewController animated:NO];
That switches the view, but hides the UITabBar. How to keep the bar on the screen after the switch?
P.S. Sorry for the blurred image. I am not allowed to share to much info.
Well I think you are misusing the modal view controller. For a problem like this I'll say you should put them in a view controller stack using UINavigationController. Instead of making each tab a UIViewController make it a UINavigationController, then you can push and pop view controllers on it, which still show the tab bar.
See http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UINavigationController_Class/Reference/Reference.html
use: tabBarController.selectedViewController = newViewController
edit: UINavigationController is not needed here.
Here is my problem:
I've read a lot about how to use a tab bar within a navigation based application, but i still can't figure it out. I have tried both to use and avoid using a tab bar controller, but i just can't find the solution.
I already have a navigation based app working. I have several nib files (views), each one with its own view controller, that i programmatically push onto the navigation controller stack. I need one of this views to have a tab bar that allows me to switch between some of the others. I understand how the tab bar works, and i do think what i need is to use a tab bar controller, since it would allow me to define the view controllers associated with each tab bar item, and manage all about them. However, i can't see how to do it.
If i do declare a tab bar controller in my "tabBarViewController", draw the tab bar controller in my "tabBarView" and link them with the IB, it will give me an error (I reckon this is because i haven't really pushed the tab bar controller's view? do i need something equivalent to "[window addSubView:[tabbarcontroller view]]?). In this case, all i need to know is how to "see" the tab bar controller's top view controller's view within a view controller i have already pushed.
If i try not to use a tab bar controller, as i have read is the best solution to this problem, ¿how do i manage tab bar items, the switchs between them, etc?
I would really appreciate your help.
You can't push a tab bar controller onto a navigation controller stack. There's just no supported way to do it.
What you may want to consider instead is creating your own instance of UITabBar, then using a delegate that conforms to UITabBarDelegate. That way, your delegate will receive the tabBar:didSelectItem: message whenever a tab bar item is selected by the user. You'll have to manage the NSArray of items for the bar yourself, though, without using IB.
Once you've got that figured out, all that's left to do is push a regular UIViewController onto your navigation stack like any other, and just have that controller manage your tab bar and delegate.
I just made an App with a tabBar controller and 5 navControllers. All you need to do is load the nibs and navigation controller inside the first element of the tabBar controller. You can HIDE the tabBar even if the views are inside it, and make it appear in the view you need it to.
You can do this with a bit of code, like so:
FooViewController *foo = [[FooViewController alloc] init];
BarViewController *bar = [[BarViewController alloc] init];
UITabBarController *tabby = [[UITabBarController alloc] init];
[tabby setViewControllers:[NSArray arrayWithObjects:foo, bar, nil] animated:NO];
[self.navigationController pushViewController:tabby animated:YES];
[foo release];
[bar release];
[tabby release];
You could probably do it with IB as well, just load the tab bar controller from a nib.
I built a sample project that demonstrates this in action, you can download it from http://s3.thismoment.com/navtab.zip
This question has probably been asked before, but my google-fu must be inferior to everybody else's, cause I can't figure this out.
I'm playing around with the iPhone SDK, and I'm building a concept app I've been thinking about. If we have a look at the skeleton generated with a navigation based app, the MainWindow.xib contains a navigation controller, and within that a root-view controller (and a navigation bar and toolbar if you play around with it a little). The root-view controller has the RootViewController-nib associated with it, which loads the table-view.
So far so good. To add content to the tool bar and to the navigation bar, I'm supposed to add those to in the hierarchy below the Root View Controller (which works, no problem). However, what I can't figure out is, this is all still within the MainWindow.xib (or, at runtime, nib). How would I define a xib in order for it to pick up tool bar items from that?
I want to do (the equivalent of, just reusing the name here)
RootViewController *controller = [[RootViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
and have the navigation controller pick-up on the tool bar items defined in that nib. The logical place to put it would be in the hierarchy under File's Owner (which is of type RootViewController), but it doesn't appear to be possible.
Currently, I'm assigning these (navigationItem and toolbarItems) manually in the viewDidLoad method, or define them in the MainWindow.xib directly to be loaded when the app initializes.
Any ideas?
Edit
I guess I'll try to explain with a picture. This is the Interface Builder of the main window, pretty much as it comes out of the wizard to create a navigation based project. I've added a toolbar item for clarity though. You can see the navigation controller, with a toolbar and a navigation bar, and the root view controller.
IB Screenshot http://img526.imageshack.us/img526/3507/rootviewcontroller.png
Basically, the Root View Controller has a bar button item and a navigation item as you can see. The thing is, it's also got a nib associated with it, which, when loaded will instantiate a view, and assign it to the view outlet of the controller (which in that nib is File's Owner, of type RootViewController, as should be).
How can I get the toolbar item, and the navigation item, into the other nib, the RootViewController.nib so I can remove them here. The RootViewController.nib adds everything else to the Root View Controller, why not these items?
The background for this is that I want to simply instantiate RootViewController, initialize it with its own nib (i.e. initWithNibName:nil shown above), and push it onto the navigation controller, without having to add the navigation/toolbar items in coding (as I do it now).
First off, the way you've worded your question is a bit confusing here, but I think I understand.
You've got a couple options here. If you want to design your toolbar, just add one to the view you are loading and drag the various buttons and separators onto it in Interface Builder. Then create IBActions in that view's view controller and drag connections from your toolbar items to the various actions. Since you are using a Navigation controller, though, you will want to hide the toolbar you get by default by unchecking the "Shows Toolbar" box in your MainWindow.xib when the UINavigationController is selected (Attributes tab in the IB inspector).
alt text http://cimgf.com/files/toolbarthing.png
Alternatively, you can just add toolbar items programmatically in the viewDidLoad method by calling [self setToolbarItems:items]; where items is an NSArray of toolbar items.
Really there is no way that I'm aware of to cause the navigation controller to use your custom toolbar. Just hide the main one and use your custom one.