IPhone SDK: TabBars

Programatically Creating Tab Bars

This is a tutorial for beginners to the IPhone SDK and includes instructions on programatically creating a Tab Bar Controller with two Tabs and their associated views. As an illustration of how interface elements from one view can interact with those on other views I have placed a UITextField and Button on one view and a UILabel on the other. Anything typed in the text field will be copied to the label when the button is clicked. I will be using the 2.0 SDK so some features may not be available in the earlier version.


Step 1: Read the Hello World tutorial


If you are are unfamiliar with developing in Objective C and IPhone SDK please take a moment to go through the earlier tutorial IPhone SDK Hello World. It also contains instructio
ns on how to install XCode and the IPhone SDK.

Step 2: Create a project



Select File > New Project or Apple Key + Shft + N to bring up the new project menu. Select the Applications item of the IPhone OS section from the menu on the left, and select Window Based Application from the icons on the right. When prompted enter a project name, I have used TabBar in the sample code. You should have two files TabBarAppDelegate.h and TabBarAppDelegate.m.


Step 3: Create the View Controllers


We are going to create two tabs and we need a view controller for each one. Hence Create two files of type UIViewController SubClass. I named the files View1Controller.m and View2Controller.m Make sure you check the box to also create the header file.

Now You should have Six files in your project:
TabBarAppDelegate.m
TabBarAppDelegate.h
View1Controller.m
View1Controller.h
View2Controller.m
View3Controller.h















Step 4: Setup the View Controllers

View1Controller

First we will setup the view containing the Button and Text Field. Browse to the View1Controller.h header file and add the following interface elements, UITextField, UIButton, UIView and also add a reference to the Application delegate which will be used to communincate between views. We also create properties for each of the variables we have defined. The final code should look something like this:

1    #import <UIKit/UIKit.h>
2    #import "TabBarAppDelegate.h"

@class TabBarAppDelegate;
2    @interface View1Controller : UIViewController
3    {
4        UITextField                *textField;
5        UIButton                    *cmdButton;
6        UIView                       *myView;
7        TabBarAppDelegate  *delegateRef;
8    }
9    
10   @property (nonatomic, assign)    UITextField                  *textField;
11   @property (nonatomic, assign)    UIButton                      *cmdButton;
12   @property (nonatomic, assign)    UIView                        *myView;
13   @property (nonatomic, assign)  TabBarAppDelegate   *delegateRef;
14
15   @end


In the View1Controller.m file synthesize the properties and write and init method to create the user interface elements. Technically this should be in the load view method but since I am allowing one view to directly access another I need them to be initlized even if they are not loaded. The proper way to do this is to store data seperately and pull it when the view is loaded but i want to keep this tutorial simple.

1    - (id)init
2    {
3        if (self = [super init])
4        {
5            // Initialization code
6            self.title = @"Text and Button"; //Set View title which will be displayed in Tab Bar
7            // create and configure the view
8            CGRect cgRct = CGRectMake(0.0, 0.0, 480, 320); //define size and position of view
9            myView = [[UIView alloc] initWithFrame:cgRct]; //initilize the view    
10          myView.autoresizesSubviews = YES;              //allow it to tweak size of elements in view
11          self.view = myView;                            //set view property ov controller to the newly created view
12       
13          // create a UIButton (UIButtonTypeRoundedRect)
14          cmdButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];    
15          cmdButton.frame = CGRectMake(100, 100, 100, 50);
16          [cmdButton setTitle:@"Click Me" forState:UIControlStateNormal];
17          cmdButton.backgroundColor = [UIColor clearColor];
18          [cmdButton addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
19          cmdButton.adjustsImageWhenHighlighted = YES;
20      
21          //create a text field
22          cgRct = CGRectMake(60, 170, 200, 50); //define size and position of textbox
23          textField = [[UITextField alloc] initWithFrame:cgRct];
24          textField.text = @"Enter Text Here";
25          textField.borderStyle = UITextBorderStyleBezel;
26       
27          //Add text field and button to main view
28          [self.view addSubview:cmdButton];
29          [self.view addSubview:textField];
30      }
31      return self;
32   }

Also we need to add an action handler to take care of the button click. Add the following method to View1Controller.m. Note that view are accessing the label using the view controller that we reference using the AppDelegate instance pointed to by the delegateRef property. 

1    - (void)action:(id)sender
2    {
3        [self.textField resignFirstResponder]; //Hide Keyboard
4        self.delegateRef.view2Controller.label.text = self.textField.text;//Ubdate label
5    }


View2Controller


On tot he second view controller, we do not keep an app delegate instance here because this view does not need to initiate any interaction with the first view. If this were not the case then we would also keep a reference here

1    #import <UIKit/UIKit.h>

2    @interface View2Controller : UIViewController
3    {
4        UILabel    *label;
5        UIView    *myView;
6    }
7
8    @property (nonatomic, assign)     UILabel    *label;
9    @property (nonatomic, assign)    UIView      *myView;
10
11   @end


In the View2Controller.m file synthesize the properties and write and init method to create the user interface elements.

Step 5: Setting Up the App Delegate


In the TabBarAppDelegate.h header file we define instances of the UITabBarController as well as the two views we have just setup. We create properties for these variables an also declare he relevent classes and import the relevent header files. The final code should look something like this:

1    #import <UIKit/UIKit.h>
2    #import "View1Controller.h"
3    #import "View2Controller.h"

4    @class TabBarViewController;
5    @class View1Controller;
6    @class View2Controller;

7    @interface TabBarAppDelegate : NSObject <UIApplicationDelegate>
8    {
9        UIWindow *window;
10      UITabBarController *tabBarController;
11      View1Controller *view1Controller;
12      View2Controller *view2Controller;
13  }
14
15   @property (nonatomic, assign) UIWindow *window;
16   @property (nonatomic, assign) UITabBarController *tabBarController;
17   @property (nonatomic, assign) View1Controller *view1Controller;
18   @property (nonatomic, assign) View2Controller *view2Controller;
19   @end

In the implementtion file TabBarAppDelegate.m update the applicationDidFinishLaunching method to create the view controllers and the tab bar controllers and add them to the window. The code for this is as follows.

1    @synthesize window;
2    @synthesize view1Controller;
3    @synthesize view2Controller;
4    @synthesize tabBarController;

5    - (void)applicationDidFinishLaunching:(UIApplication *)application
6    {   
7        //Initilize objects
8        tabBarController = [[UITabBarController alloc] init];       
9        view1Controller = [[View1Controller alloc] init]; 
10      view2Controller = [[View2Controller alloc] init];  
11   
12      //Add a refernce to self in the View1Controller so that it can reference View2Controller via this object
13      view1Controller.delegateRef = self;
14   
15      //Add views to the TabBar
16      tabBarController.viewControllers = [NSArray arrayWithObjects:view1Controller, view2Controller, nil];    
17   
18      //Add tabbar to window and display
19      [window addSubview:tabBarController.view];                                            
20      [window makeKeyAndVisible];
21  }



Step 6: Build and Go


Click the Build an Go button to run your code and you should see the Tab Bar with the first view Loaded. Enter your teck and click the button on the screen. Now load the seconf view by clicking the right Tab and see your text updated there.

























Step 7: Extra Credit Adding Icons


Create two 32 x 32, 150 dpi, grey scale png images that you want to use as icons I called mine icon.png and icon1.png. Import the images into the resources folder by right clicking it and selecting Add > Existing Files... and selecting the image files. Now in the init method of both ViewControllers (View1Controller and View2Controller) add the following lines respectively.

        self.tabBarItem.image = [UIImage imageNamed:@"icon.png"];
        self.tabBarItem.image = [UIImage imageNamed:@"icon1.png"];

Click Build and Go to see the icons.

 

Concluding Note


I hope this tutorial was clear and helpful let me know if there are any problems or if it can be improved. Also please download the XCode project source from my site Here




Comments

PNG file

Hi Every one,

Ok I have a few questions about these icons.
I'm a graphic designer and I don't want to keep sending files to the programmer to compile for me to look at only for them to look totally shit. I have sent so many already :/ I just cant get it right.

How do I make a nice looking circle if I can only use solid pixles,
every thing looks Jaged, (not like the head in the facebook app)

If I make a circle in illustrator then past that into photoshop on a 32X32 RGB file
then the circle comes through with a heap of nice anti aliasing so that the cirle looks smooth.

I have a transparent background layer.(photoshop checkerboard)

I save as 8bit 16 color PNG

but then the iphone compiler turns all the anti Aliasing into solid which looks nasty.

What would happen if I created a a solid black png then did a nice anti aliased Alpha Channel and saved it as a 24 bit PNG?

Whould that work?

If not then how do you create nice smooth icons?

thanks so much every one :)
J

Last edited Dec 7, 2008 5:05 PM
Report abusive comment

Question to -(id)init

I have a question concerning the init method. Do I have to perform a special task to call the (id)init-method?
I've implemented an init-Method in my own application but it never gets called. I thought a init method get called always when the application is started and it is used for initialising tasks. Is this wrong?
Thanks for your help!

Last edited Dec 3, 2008 5:11 AM
Report abusive comment

Disadvantages of using Interface Builder

1. I've read in some forums that the usage of Interface Builder should be avoided and instead the interface should be built up programmatically. Is this true?

Because all the Apple Iphone Guides encourage you to use the IB.



2. Regarding your init(id) method in your View1Controller class: The way you set up the view in this method, don't you run the risk of using to much memory? Or to consume too much resources?

I'm asking because you're writing yourself that it isn't the best solution.

Last edited Nov 14, 2008 4:36 AM
Report abusive comment

Assign vs Retain

Hello Usman

Thanks for providing this great resource to the iPhone community!

I do have one question concerning the use of assign instead of retain for the TabBarAppDelegate.
Most of the examples in the SDK use Retain for the properties and I don't really understand your explanation.
How do you decide which one to use and what are the implications with regards to memory leaks?

Thanks again.

Last edited Aug 27, 2009 6:13 PM
Report abusive comment

Interface Builder?

Hi Usman,

This tutorial is exactly what I needed to get deeper into tabbars! I have one newbie question; How can I use interface builder to create the UI? I've tried about everything I can think of and am starting to feel a little dumb. Thanks!

Last edited Sep 15, 2008 11:28 AM
Report abusive comment

Question about the hand off

This is the best tut I've found so far, baravo. The only question I have is about the hand off from the first to the second controller.

Last edited Sep 12, 2008 2:28 PM
Report abusive comment
Article rating:
Your rating:

Activity for this knol

This week:

122pageviews

Totals:

14621pageviews
20comments