Wednesday, November 10, 2010

creating a UITabBarController


I will show you how to create a UITabBarController application using only code. You’ll notice that this app doesn’t really “do” anything, it just switches between two table view controllers, but I think this will give you the framework to create a tab bar-based application and have the view controllers do whatever you want in your own app. To the left you can see what the final app looks like (thank you to Apple Computer, Inc. for the tab button images which I took from the Elements model app).
Just some conditions on why I am doing this programmatically as an alternative of using Interface Builder (IB). The primary reason is that I don’t really like IB that much because it obfuscates a lot of what is going on and sometimes can make it hard to debug your applications. I’m not saying that I will never use IB, I’d just rather figure out how to do something first without using IB and then if I choose to use IB afterward I can, and I’ll know what’s going on under all of those covers that IB puts on top of your code.
Before we dive in, a quick note about UITabBarControllers. UITabBarControllers work by providing them an array of outlook controllers (table view controllers, navigation controllers, plain vanilla view controllers, etc.) and assigning that array to the viewControllers property of your UITabBarControllers object. That’s cute straightforward, except that there are some subtle details you need to get right or your program won’t work and most likely crash when you run it. One other important thing is that if you read Apple’s “View Controller Guide for iPhone OS” it will tell you that the correct way to create a UITabBarController object is with the subsequent code:
tabBarController = [[UITabBarController alloc] initWithNibName:nil bundle:nil];
This is WRONG. Instead, you just need to this:
tabBarController = [[UITabBarController alloc] init];
and that’s it. From searching various forums it seems like this is a common problem people have.
So let’s dive into this from scratch. I’m going to assume you have used XCode before and know at least some essential Objective-C and iPhone programming.
1. Open XCode and select File > New Project > Window-basedApplication (under iPhone OS Application). We’ll be doing all of this by hand so no need to have XCode stub out view controller classes for us or anything like that. Name the project whatever you want. I called mine “SimpleTabBar”.
2. Now we’ll create two table view controllers that will be shown when we click each tab in the tab bar. Right (Ctrl) click on the “Classes” folder and select Add > New File. Under iPhone OS > Cocoa Touch Classes select UITableViewController subclass and click next. Name your class something like “RootViewController.m” and don’t forget to create the .h file also. Do the same thing to generate your second view controller and call it something like “SecondViewController.m”.
3. You should now have three classes: SimpleTabBarAppDelegate, RootViewController, and SecondViewController. Within the border section of SimpleTabBarAppDelegate, add the following two instance variables (“window” will already be there for you). Declare them as properties also so that your code looks like this:
@interface SimpleTabBarAppDelegate : NSObject {
UIWindow *window;
UITabBarController *tabBarController;
}
@property (nonatomic, retain) UITabBarController *tabBarController;
@property (nonatomic, retain) UIWindow *window;
As you have probably guessed, tabBarController is the thing which will be used to create our tab bar controller. In my example, XCode also added an IBOutlet type in front of UIWindow in the property announcement for window, but you don’t need that so I impassive it.
4. Now go to the implementation section of SimpleTabBarAppDelegate and we’ll add some code to populate our tabBarController with an array of table view controllers (RootViewController and SecondViewController). I’ll break this down by sections. First, embrace the header files for the two view controller classes because we will be creating view controller classes from within SimpleTabBarAppDelegate. Just under the line where it says #import “SimpleTabBarAppDelegate” insert the following two lines:
#import “RootViewController.h”
#import “SecondViewController.h”
Also add the following line:
@synthesize tabBarController;
just under @synthesize window;
5. Within the applicationDidFinishLaunching process, let’s instantiate a UINavigationController, within which each of our UITableViewControllers will live. This will make it nice for users to browse back and forth in your tables within your app.
// set up a local nav controller which we will reuse for each view controller
UINavigationController *localNavigationController;
6. Remember on top of I said that a UITabBarController class just holds an array of view controllers? So let’s get started doing that by creating our tab bar controller item and an array that will hold all of those view controllers.
// create tab bar controller and array to hold the view controllers
tabBarController = [[UITabBarController alloc] init];
NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:2];
Change “initWithCapacity” to however many tabs you will have, 2 in this case.
7. Now let’s get to work creating those view controllers and adding them to the array. First, let’s do the origin view controller. Note that I basically create the root view controller and then add it to the steering controller as its “root” view manager.
// setup the first view controller (Root view controller)
RootViewController *myViewController;
myViewController = [[RootViewController alloc] initWithTabBar];
// create the nav controller and add the root view controller as its first view
localNavigationController = [[UINavigationController alloc] initWithRootViewController:myViewController];
// add the new nav controller (with the root view controller inside it)
// to the array of controllers
[localControllersArray addObject:localNavigationController];
// release since we are done with this for now
[localNavigationController release];
[myViewController release];
For now don’t worry about the initWithTabBar method. It’s a custom init method that I’ll describe later.
8. Do the same thing for the second view controller (SecondViewController):
// setup the second view controller just like the firstSecondViewController *secondViewController;
secondViewController = [[SecondViewController alloc] initWithTabBar];
localNavigationController = [[UINavigationController alloc]
initWithRootViewController:secondViewController];
[localControllersArray addObject:localNavigationController];
[localNavigationController release];
[secondViewController release];
9. Now let’s load up our tab bar controller with the array of view controllers.
// load up our tab bar controller with the view controllers
tabBarController.viewControllers = localControllersArray;
// release the array because the tab bar controller now has it
[localControllersArray release];
// add the tabBarController as a subview in the window
[window addSubview:tabBarController.view];
// need this last line to display the window (and tab bar controller)
[window makeKeyAndVisible];
10. Practice good memory mgmt by releasing the window and tabBarController objects.
- (void)dealloc {
[tabBarController release];
[window release];
[super dealloc];
}
11. Ok – so that was the lions share of the work that is necessary. Now let’s go to each view manager and make some small changes to get this thing to compile and run! For each view controller, we are basically going to do the same thing but just change the titles so that it says “Tab1″ instead of “Tab2″ on the monitor. So I won’t show you the code from both view controllers, just make sure it is the same for each except for the text label changes. First, let’s declare our convention initialization method (“initWithTabBar”) in the interface section of RootViewController.h. As follows:
@interface RootViewController : UITableViewController {
}
-(id)initWithTabBar;
@end
12. Now let’s go to the realization section and put in the code for that custom init method. Note that there is more than one way to skin this cat, and you might want to just put this code into the “initWithStyle” method that is already there in case you want to specify a style for your table. But I did it this way just to show a custom initialization method in action.
-(id) initWithTabBar {
if ([self init]) {
//this is the label on the tab button itself
self.title = @”Tab1″;
//use whatever image you want and add it to your project
self.tabBarItem.image = [UIImage imageNamed:@"name_gray.png"];
// set the long name shown in the navigation bar at the top
self.navigationItem.title=@”Nav Title”;
}
return self;
}
I think the comments here are pretty self-explanatory, but let me know if you have any questions!
13. Go ahead and do the same thing in your SecondViewController class and change the titles to “Tab2″ etc.
14. Click the Compile and Go button and see the outcome of your work. Let me know if you have any questions!
Once you get this to work, you can add as many views and buttons as you want. Just create as many view controllers as you need and do again the steps in in your AppDelegate class for each view. Also don’t forget to alter the size of your array when you initialize it.

No comments:

Post a Comment

Followers