»
January 24, 2009
»

Creating UITabBarController Based App Using Interface Builder

I’ll try to describe the process of creating UITabBarController based app mainly using Interface Builder. The UITabBarController will manages two UIViewControllers with views stored in Nibs.

Window-Based Application

We will start with creating a Window-Based Application. Click on File → New Project and select iPhone OS → Applications → Window-Based Application:

thumbs/1.png

I’ll Name it TabBarExample.

The initial project layout should look like this:

thumbs/2.png

Before we start with Interface Builder, let’s add outlet for UITabBarController in TabBarExampleAppDelegate:

// TabBarExampleAppDelegate.h

#import <UIKit/UIKit.h>

@interface TabBarExampleAppDelegate : NSObject <UIApplicationDelegate>
{
   UIWindow *window;
   UITabBarController *tabBarController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;

@end
// TabBarExampleAppDelegate.m

@implementation TabBarExampleAppDelegate
@synthesize window;
@synthesize tabBarController;

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
   [window makeKeyAndVisible];
}

- (void)dealloc
{
   self.window = nil;
   self.tabBarController = nil;
   [super dealloc];
}

@end

Notice @property and @synthesize for tabBarController property.

We will use this property to connect UITabBarController in Interface Builder because we need to add Tab Bar Controller’s view to window as subview.

Interface Builder

Next, create Tab Bar Controller.

Open MainWindow.xib.

thumbs/3.png

Notice that Tab Bar Example App Delegate has two outlets: window and tabBarController.

Create UITabBarController by draging it from Library → Controllers → TabBarController to MainWindow.xib.

Now we have new a window in Interface Builder named Tab Bar Controller:

thumbs/4.png

Connect Tab Bar Controller to Tab Bar Example App Delegate by right clicking on App Delegate and dragging the line from tabBarController outlet to actual Tab Bar Controller instance.

thumbs/5.png

Back to Xcode

Altrough we haven’t created any UIViewController instances for Tab Bar Controller to manage, we can still add blank Tab Bar to window and ensure it’s visible and we’re still on right track this far.

To do so, open TabBarExampleAppDelegate.m and in -applicationDidFinishLaunching: method add tabBarController’s view as a subview to the window:

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
   [window addSubview:[tabBarController view]];
   [window makeKeyAndVisible];
}

Finally now it’s time to run this thing:

thumbs/6.png

As you can see, there’s UITabBar view with two tabs but above it — just white background. It’s window’s background without anything on top of it. Next we will add views what (by using UITabBarController) will be shown there.

UIViewControllers

So we need to create two UIViewController subclasses. I’ll call them WelcomeViewController and AboutViewController.

To create them, select:
File → New File → Cocoa Touch Classes → UIViewController subclass:

thumbs/7.png

Set the file name to WelcomeViewController.m and click Finish. Then in same manner create AboutViewController class.

thumbs/8.png

Creating XIBs

Now we need views for those two view controllers. For this example they’ll be XIB’s.

Create two XIB’s named after controllers what will manage them by selecting:
File → New File → User Interfaces → View XIB

thumbs/9.png

Back to Interface Builder

In Interface Builder close MainWindow.xib and (from Xcode) open WelcomeViewController.xib.

Set File’s Owner class to be WelcomeViewController and add some label what will let us to make distinction between both controller views.

thumbs/10.png

By the way, that black bottom bar what is visible over view is simulated. To show/simulate it, select View and in Inspector’s View Attributes select Tab Bar as Bottom Bar value.

The last thing we need to do here is connect XIB’s UIView instance to controller’s view outlet otherwise controller won’t be able to add it as a parent’s (UITabBarController’s view) subview.

Right click on File’s Owner and drag the line from view outlet to the View.

thumbs/11.png

Repeat the same steps with AboutViewController controller-view pair.

MainWindow.xib

The last thing we need to do is to connect UITabBarItems with our newly created view controllers.

Open MainWindow.xib from Xcode. Open Tab Bar Controller, select first item (named “Item 1”), in Inspector (ensure the selected item is “View Controller” not “Tab Bar Item”).

Set view controller’s NIB name to WelcomeViewController and AboutViewController for other UITabBarItem. Set the class (in Identity tab) to WelcomeViewController for the first one and AboutViewController for other one.

Now the view placeholder should show “Loaded from” message:

thumbs/12.png

…and Inspector palettes should contain:

thumbs/13.pngthumbs/14.png

Select UITabBarItem, set icon and/or title for both of them (or just leave “Item 1” and “Item 2”).

thumbs/15.png

And we’re done.

UITabBarController switches UIViewController instances what manages the loading of XIBs.

Run and try to click/tap on both tabs, the view should change.

thumbs/16.png

Extra — Adding a click counter badge

Just a simple example accessing UITabBarItem directly from code. Using delegate, we will be counting clicks on the tab bar and updating badge for one of the tab bar items.

Add UITabBarItem outlet for TabBarExampleAppDelegate, set TabBarExampleAppDelegate to adopt UITabBarControllerDelegate protocol and implement optional -tabBarController:didSelectViewController delegate method:

// TabBarExampleAppDelegate.h

#import <UIKit/UIKit.h>

@interface TabBarExampleAppDelegate : NSObject <UIApplicationDelegate,                     ↩
  UITabBarControllerDelegate> {
   UIWindow *window;
   UITabBarController *tabBarController;
   UITabBarItem *tabBarItem;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
@property (nonatomic, retain) IBOutlet UITabBarItem *tabBarItem;

@end
// TabBarExampleAppDelegate.m

#import "TabBarExampleAppDelegate.h"

@implementation TabBarExampleAppDelegate
@synthesize window;
@synthesize tabBarController;
@synthesize tabBarItem;

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
   [window addSubview:[tabBarController view]];
   [window makeKeyAndVisible];
}

- (void)dealloc
{
   self.window = nil;
   self.tabBarController = nil;
   self.tabBarItem = nil;
   [super dealloc];
}

- (void)tabBarController:(UITabBarController *)tabBarController 
 didSelectViewController:(UIViewController *)viewController
{
   NSLog(@"-didSelectViewController:%@", viewController);
}

@end

Open MainWindow.xib and connect Tab Bar Example App Delegate’s tabBarItem outlet to one of the UITabBarItems:

thumbs/17.png

Set Tab Bar Example App Delegate to be Tab Bar Controller’s delegate:

thumbs/18.png

Run the app and ensure delegate callback is called:

[Session started at 2009-01-24 17:24:47 +0200.]
-didSelectViewController:<WelcomeViewController: 0x526000>
-didSelectViewController:<AboutViewController: 0x5262c0>
Terminating in response to SpringBoard's termination.

Next, add NSUInteger instance variable named count and set it to zero in -applicationDidFinishLaunching:

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
   self.count = 0;
   [window addSubview:[tabBarController view]];
   [window makeKeyAndVisible];
}

Then in -tabBarController:didSelectViewController set current count to tabBarItem.text property and increment the count:

- (void)tabBarController:(UITabBarController *)tabBarController 
 didSelectViewController:(UIViewController *)viewController
{
   NSLog(@"-didSelectViewController:%@", viewController);
   tabBarItem.badgeValue = [NSString stringWithFormat:@"%i", self.count];
   self.count = self.count + 1;
}

Run the app and ensure badge is updated:

thumbs/19.png

Download “TabBarExample.zip” (28Kb)

Note about items in Nibs

In this example I used existing UITabBarItems but they can be kept in each view’s Nib to improve encapsulation. To do so, just create Tab Bar Item in view’s XIB:

thumbs/20.png

…and connect it to File’s Owner tabBarItem outlet:

thumbs/21.png

 
Internet Explorer 6
Are you serious?