Throwing a UINavigationController, UITabBarController and UISearchBar Together

In my "last blog post":http://jduff.github.com/2010/03/01/building-a-searchview-with-uisearchbar-and-uitableview/ I did a tutorial on building a SearchView using _UISearchBar_ and _UITableView_. This time around I'm going to talk about mixing together a _UINavigationController_, _UITabBarController_ and _UISearchBar_ together to see what we get. For this post I'm starting out with a brand new project and doing everything from there, but it should be trivial to do this in the same project as last time (that's actually what I did the first time around). As always, if all you care about is the code "be my guest":http://jduff.github.com/2010/03/09/throwing-a-uinavigationcontroller-uitabbarcontroller-and-uisearchbar-together/#-2010-03-09-throwing-a-uinavigationcontroller-uitabbarcontroller-and-uisearchbar-together-full-code, but be warned, we're doing a lot more in Interface Builder this time. h3. Background Okay, so what exactly are we going to build this time? We're going to start with a Tab Bar application which is going to have a _UINavigationController_ as one of its View Controllers. Once we get this all set up we're going to add a _UISearchBar_ as the _navigationItem_ of the initial view. When we're all done we'll have something like this: p=. !{max-height:500px}/images/posts/2010-03-09/uisearchbar_simulator.png(Search Bar in Navigation Item)!!{max-height:500px}/images/posts/2010-03-09/add_table_view_controller_simulator_2.png(Details View)! So we have the _UISearchBar_ in the _navigationItem_ and when we push another View Controller onto the stack it slides over nicely to give you the back button. h3. Setting up the Project As I said earlier I am starting with a Tab Bar application but you should be able to use any starting point for the application you would like. I wont go into the details of creating the initial project but once you're ready to go and have a _UITabBarController_ in there (the Tab Bar application gives one to you) open up the Main Window Nib and take a look at it. p=. !{max-height:400px}/images/posts/2010-03-09/initial_ib.png(Initial View from Interface Builder)! This is pretty straight forward, we have the _UITabBarController_ and it has a couple of View Controllers that it switches between. If you run the app right now this is what you would see: p=. !{max-height:500px}/images/posts/2010-03-09/initial_simulator.png(Initial Simulator Rub)! Simple. Lets add the _UINavigationController_ h3. Adding the Navigation Controller to the Mix Okay, lets switch back to Interface Builder and drop the _UINavigationController_ into the Nib *inside of* the _UITabBarController_. Here's what we're looking at after that: p=. !{max-height:400px}/images/posts/2010-03-09/add_nav_controller_ib.png(Add the Navigation Controller)! Notice how it's inside the _UITabBarController_ and another button was added to the Tab Bar? Next we want to add another View for the _UINavigationController_ to display. I just created a new _UITableViewController_ (Xcode File -> New File) from Xcode and added it to the project. p=. !{max-height:400px}/images/posts/2010-03-09/add_table_view_controller_xcode.png(Add Table View to the Project)! With that added we switch back to Interface Builder and change the class for the _UIViewController_ that is inside the _UINavigationController_. p=. !{max-height:400px}/images/posts/2010-03-09/add_table_view_controller_ib.png(Change the View Controller Class)! All we had to do is select the current View Controller in the Nib and then in the Identity Inspector select our new Class in the Class drop down. Now when we run the project we see our Table View show up along with the Navigation Bar. p=. !{max-height:500px}/images/posts/2010-03-09/add_table_view_controller_simulator.png(Search View Faded with Results)! Okay, we're just about done. Next we're going to add that Search Bar to the Navigation Bar. h3. Pushing the Search Bar into the Navigation Bar Alright, time to actually get in and add some code! Lets get into Xcode and open up that Table View Controller we created and add a few lines to the _viewDidLoad_ method.
//  TableViewController.m

#import "TableViewController.h"

@implementation TableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
	
	// Creating the UISearchBar and adding it to the 
	// UINavigationController
	UISearchBar *theSearchBar = [[UISearchBar alloc]
	    initWithFrame:CGRectMake(0.0f,0.0f,320.0f,0.0f)];
	[theSearchBar sizeToFit];
	self.navigationItem.titleView = theSearchBar;
	self.navigationItem.titleView.autoresizingMask = 
	    UIViewAutoresizingFlexibleWidth;
	[theSearchBar release];
}

@end
The main thing to take note of here is that we're adding the Search Bar to the _navigationItem.titleView_ and then setting the _autoresizingMask_ on it to be flexible. This might seem like a bit of a hack, and it very well might be, but it does the job. I also called _sizeToFit_ on my SearchBar so that it would expand to fit the whole bar. Let's take a look. p=. !{max-height:500px}/images/posts/2010-03-09/uisearchbar_simulator.png(Search Bar in Navigation Item)! There we have it! Now when you select an item from the Table View and push another View Controller onto the stack the Search Bar slides out of the way for the back Bar Item. If you take a look at the full code below you'll see how to do this. Something to note, if you want to change the color of the Navigation Bar you will also want to set the tint on the Search Bar so it fits in.
theSearchBar.tintColor = [UIColor colorWithRed:0.0f green:0.0f 
    blue:0.0f alpha:0.5f];
This will set the tint to be black, very much like the 'Black Opaque' style that can be set on may UI elements. h3. Conclusion There we go, we have a Tab Bar with a Navigation Bar for one of the items and we've pushed a Search Bar into the Navigation Bar. I've included the code below along with some of the generated methods for the Table View Controller that I hooked up. If you have any suggestions or feedback please "leave a comment":http://jduff.github.com/2010/03/09/throwing-a-uinavigationcontroller-uitabbarcontroller-and-uisearchbar-together/#comments!
//
//  TableViewController.m

#import "TableViewController.h"
#import "FirstViewController.h"


@implementation TableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
	
	// Creating the UISearchBar and adding it to the UINavigationController
	UISearchBar *theSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0f,0.0f,320.0f,0.0f)];
	[theSearchBar sizeToFit];
	self.navigationItem.titleView = theSearchBar;
	self.navigationItem.titleView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
	[theSearchBar release];
}

- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
	
	// Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}


#pragma mark Table view methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}


// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
    
    cell.textLabel.text = @"first cell";
	
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here. Create and push another view controller.
	FirstViewController *anotherViewController = [[FirstViewController alloc] initWithNibName:@"SecondView" bundle:nil];
	[self.navigationController pushViewController:anotherViewController animated:YES];
	[anotherViewController release];
}

- (void)dealloc {
    [super dealloc];
}


@end
March 09, 2010 | programming, iphone, objective-c, uinavigationcontroller, uitabbarcontroller, uisearchbar
About | Blog | Archives | Resume | RSS