Tuesday, February 8, 2011

How To Start UITabBarController and Its Delegate

1. Create a “Window-Based” application template
I had originally intended to create the application based on a “Navigation-Based” application template but now I have decided to create everything from scratch and not use Interface Builder. So if you have already completed part 2 then I suggest you go back there and follow the instructions to create the new “Window-Based” application template.

2. Setting up the UITabBarController and its delegate

Open up RSSReaderAppDelegate.h and edit the code to look like below

#import <UIKit/UIKit.h>

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

What we have done here is added the UITabBarControllerDelegate and created a UITabBarController instance called tabBarController.
Now you will need to open up RSSReaderAppDelegate.m and synthesize the tabBarController instance and alter the applicationDidFinishLaunching function to look like this

- (void)applicationDidFinishLaunching:(UIApplication *)application {

tabBarController = [[UITabBarController alloc] initWithNibName:nil bundle:nil];
// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];
}

This will allocate and init the UITabBarController and then add it to the window (we haven’t added any buttons yet, but we will do this shortly).
If you run your application now you should see the UITabBar at the bottom of the window like so:
UITabBar with no buttons

3. Creating our UINavigationController

Right Click on the Classes folder in the left hand column and click Add > New File… , the following window will appear
XCode: Add new File
Now choose UIViewController subclass and click next, now name the class MainViewController.m and click Finish.
You should now have a MainViewController.h and a MainViewController.m file in your Classes folder. Open up MainViewController.h and edit its contents to below:

#import <UIKit/UIKit.h>

@interface MainViewController : UINavigationController {
UINavigationController *navigationController;
}
@property (nonatomic, retain) UINavigationController *navigationController;
@end

Notice we have changed the subclass from UIViewController to UINavigationController and we have added a UINavigationController instance.
Now open up MainViewController.m and edit its contents to below:

#import "MainViewController.h"

@implementation MainViewController
@synthesize navigationController;
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Main View Did Load: %@", self.tabBarItem.title);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)dealloc {
[super dealloc];
}
@end
All we have done here is synthesized the navigationController instance and put a NSLog call to display when the controller is created and what its TabBar item title was when it was created.
If you run the application now you wont see anything different, this is because we haven't added anything to the UITabBarController yet. To add the buttons you will need to open up the RSSReaderAppDelegate.m file and edit the applicationDidFinishLaunching function to look like below:

- (void)applicationDidFinishLaunching:(UIApplication *)application {

tabBarController = [[UITabBarController alloc] initWithNibName:nil bundle:nil];
// Create instances of the MainViewController for the 4 TabBar buttons
MainViewController *viewController1 = [[[MainViewController alloc] initWithNibName:nil bundle:nil] autorelease];
viewController1.tabBarItem.title = @"Browse All";
MainViewController *viewController2 = [[[MainViewController alloc] initWithNibName:nil bundle:nil] autorelease];
viewController2.tabBarItem.title = @"Most Recent";
MainViewController *viewController3 = [[[MainViewController alloc] initWithNibName:nil bundle:nil] autorelease];
viewController3.tabBarItem.title = @"Favourites";
MainViewController *viewController4 = [[[MainViewController alloc] initWithNibName:nil bundle:nil] autorelease];
viewController4.tabBarItem.title = @"Settings";
tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, viewController3, viewController4, nil];
// Add the tab bar controller's current view as a subview of the window
[window addSubview:tabBarController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];
}

What we are doing here is creating 4 instances of the MainViewController and setting the tabBarItem title (this displays below TabBar icon). Once we have created all four of the View Controllers we add them to the tabBarController by setting its viewControllers property to an array containing the pointers for our 4 View Controllers. Remember that you need to have a nil value at the end of the array to indicate the last element.
If you run your application now you should see 4 TabBar items with the titles we have assigned them above. You will also notice that we have a Navigation bar at the top of our window, as we don't have a UITableView setup yet the Navigation bar will just be blank.
iPhone SDK: RSS Reader - TabBar & NavigationController working

4. Setting up our UITableViews

Now for starters we are going to need 4 UITableViewControllers for our Browse, Recent, Favourites and Settings Tabs. We will start with the stock standard ones and customize them as we go along.
Right Click the Classes folder in the left hand column and click Add > New File...
Select UITableViewController subclass and click Next
Call the first one BrowseViewController.m and then click Finish
Repeat these steps and create a RecentViewController, FavouritesViewController and SettingsViewController
Now that we have all our stock standard UITableViewControllers created we have to connect them up, we will be doing this in the MainViewController.m file, so open it up and edit its viewDidLoad function to below:

- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Main View Did Load: %@", self.tabBarItem.title);
if(self.tabBarItem.title == @"Browse All") {
BrowseViewController *browseViewController = [[BrowseViewController alloc] init];
[self pushViewController:browseViewController animated:YES];
[browseViewController release];
} else if (self.tabBarItem.title == @"Most Recent") {
RecentViewController *recentViewController = [[RecentViewController alloc] init];
[self pushViewController:recentViewController animated:YES];
[recentViewController release];
} else if (self.tabBarItem.title == @"Favourites") {
FavouritesViewController *favouritesViewController = [[FavouritesViewController alloc] init];
[self pushViewController:favouritesViewController animated:YES];
[favouritesViewController release];
} else if (self.tabBarItem.title == @"Settings") {
SettingsViewController *settingsViewController = [[SettingsViewController alloc] init];
[self pushViewController:settingsViewController animated:YES];
[settingsViewController release];
}

}

Now this may not be the most traditional method and isn't very good for massive applications that use heaps of view controllers, etc but it worked fine for my needs and meant I only needed one UINavigationController (MainViewController). What it does is it checks the title of the TabBar item that it is linked to, it then decides which UITableViewController to push into view.
Also don't forget to #import the four new header files

#import "BrowseViewController.h"
#import "RecentViewController.h"
#import "FavouritesViewController.h"
#import "SettingsViewController.h"

If you run your application now you will wee that we have a UITableView visible on each of the TabBar items, but we currently cant tell which one is which as they all look the same.

5. Identifying and Customising our UITableViews

Starting with our BrowseViewController we want to open up the BrowseViewController.m file and alter it's viewDidLoad function to below:

- (void)viewDidLoad {
[super viewDidLoad];

self.title = @"Browse All";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:nil];
}
We have set the title to "Browse All" and we have added a button to the right hand side of the navigation bar, this button is an add button (as indicated by UIBarButtonSystemItemAdd) and currently its action is set to nil, in the future we will connect this up to an UIActionSheet.
Now go through the other three controllers (RecentViewController, FavouritesViewController and SettingsController) and just set the title, not the rightBarButtonItem!
If you run your application now you should be able to navigate through it and see the title change and on the Browse All tab you should see an add button at the top right, although it wont do anything when you press it.
Browse All TabMost Recent TabFavourites TabSettings Tab

6. Download the Project Files

Click Here to download my version of the Project files, you can use these to work your way through any problems or even to work backwards to see how I do things.

No comments: