iPhone SDK: Interface Builder Basic Training

One of the greatest tools Apple provides to its iPhone developers is Interface Builder. Interface Builder is an application that allows you, the developer, to create the Graphical User Interface (GUI) for your app in a WYSIWYG (What You Is What You Get) style editor. When the app is compiled, IB then generates all the necessary code for you. This allows you to quickly and easily create interfaces. This tutorial will guide you through the creation of interfaces in Interface Builder and the use of the different elements Apple provides

Before You Begin

Before continuing with any of the examples in this tutorial you should read Apple’s iPhone Human Interface Guidelines. This documents contains essential information about the creation of interfaces for the iPhone, and failure to conform to the guidelines it lays out could cause your app to be rejected when submitted to the App Store. This document will be discussed in more detail as we go along, and all the examples in this tutorial will conform to these guidelines.

Interface Builder Basics

Interface Builder has a fairly simple layout. It consists of four main windows, the view, the library, the nib (or xib) document browser, and the inspector. So what do each of these windows do? The view is where you construct your interface. You will drag items from the library window and onto the view to place them. The document browser allows you to browse, hierarchically, the elements you have placed in your nib file. Finally, the inspector shows you all of the different attributes of the selected element and allows you to edit them.
On the more technical side, Interface Builder allows your application source code to interact with the interface in two basic ways: outlets and actions. Outlets define an element which you will have access to in your source code, you can then make connection from your outlets to those specific UI elements in Interface Builder.
An outlet is defined like this:
  1. IBOutlet id someElement;  
The IBOutlet statement could also be put with the property declaration like so:
  1. @property(nonatomic, retain)IBOutlet id someElement;  
Either way is acceptable. An action is a special type of method which is called in response to an event (i.e. the user taps a button) which you define in Interface Builder. An action is defined by making the methods return the IBAction type, like this:
  1. -(IBAction)someAction:(id)sender;  
We’ll discuss outlets and actions in more detail later.

Buttons and Labels

Step 1: Create a New Xcode Project

The first thing you will need to do before you can play with Interface Builder is to create a new Xcode project. Open Xcode click Create a New Xcode Project, and then select a view based project. Title it “counter.”
NOTE:
Make sure that you have set your target to iPhone and not iPad in Xcode.
Creating a View Based App

Step 2: Create Outlets and Actions

Now that you have an Xcode project, we want to modify the automatically created CounterViewController to define our outlets and actions. Open up the CounterViewController.h file and modify it to look like the following:
  1. #import   
  2.   
  3. @interface CounterViewController : UIViewController {  
  4.     IBOutlet UILabel* countLabel;  
  5.     NSInteger count;  
  6. }  
  7. @property(nonatomic, retain)UILabel* countLabel;  
  8. @property(nonatomic)NSInteger count;  
  9.   
  10. - (IBAction)add:(UIButton*)sender;  
  11. - (IBAction)sub:(UIButton*)sender;  
  12. - (void)displayCount;  
  13.   
  14. @end  
This defines an integer to hold the count and an outlet to a label which will display that count. It also defines a set of methods which will receive events from IB. Now we must define an implementation for these action, so open up the corresponding CounterViewController.m file and make the following changes to it:
  1. #import "CounterViewController.h"  
  2.   
  3. @implementation CounterViewController  
  4.   
  5. @synthesize count;  
  6. @synthesize countLabel;  
  7.   
  8. - (IBAction)add:(UIButton*)sender{  
  9.     count++;  
  10.     [self displayCount];  
  11. }  
  12.   
  13. - (IBAction)sub:(UIButton*)sender {  
  14.     count--;  
  15.     [self displayCount];  
  16. }  
  17.   
  18. - (void)displayCount {  
  19.     [self.countLabel setText:[[NSString alloc]initWithFormat:@"%d", self.count]];  
  20. }  
  21.   
  22. ...  
  23.   
  24. - (void)dealloc {  
  25.     [countLabel release];  
  26.     [super dealloc];  
  27. }  
  28.   
  29. @end  
This is pretty simply file. All it does is whenever the action is called is modify the count either up or down, and then displays that count on the label.

Step 3: Create the Interface

Now expand the resources folder in Xcode and you will see three files. Two of these are Interfcae Builder .xib files. For now you can ignore the MainWindow.xib, we are going to focus on the CounterViewController.xib. Open it now, this will start interface builder and you will see a screen like this:
IB Interface Overview
Its time to start building our interface! Go over to the library tab, and grab a button and drag it onto your view. If you drag the button around for a moment, you will notice that blue guides pop up. Interfcae Builder will give you different guides to help place element within the view. You will see this more as we begin to place more elements. Do that twice. Then, find a label and place it on your view.
Now, select one of the buttons, go to the attributes tab in the inspector, and change its title to “+”. Do the same thing for the other button, but instead change its title to “-”. Double-clicking will also allow you to change the title. Double-click on the label and change its text to “0″, you may also wish to change its text alignment to center, which can be done in the attributes tab of the inspector.
Now you should have an interface that looks roughly like this:
Adding Labels

Step 4: Connect the Source to the Interface

The last thing you need to do to make your counter app work is to connect the interface and the source.
Connect the countLabel outlet to the actual label. This can be done by control clicking and dragging from the File’s Owner object, in the document window, to the label, in the view. A small, gray window will appear with two options, one will be the countLabel we defined earlier, and the other will be the view (this is a default outlet required for viewcontrollers, it will have a dash to indicate it is already connected to something). Click on the countLabel option to select it.
Displaying Outlets
Now, we are going to connect our buttons to our add and subtract actions. For our purposes you can simply control-click and drag from the buttons to the File’s owner object (and select the appropriate action for each button), however take note of the fact that if you open the connection panel on the inspector (which you can get to by pressing command+2), it lists a series of different events which you can use to trigger your actions and allow you to create a huge range of functionalities from a simple button. By default it uses the Touch Up Inside event.
Inspector View
Now you can switch back to Xcode and click build and run, and your application should launch in the simulator. If you’ve wired everything up correctly, you should be able to add and subtract from the count and you should see the label change to reflect that.

The Segmented Control

A UISegmented Control is like a couple of buttons stuck together, with one major difference. The general purpose of a UISegmentedControl is not to be like a pushbutton, but for selection. Lets expand on the functionality of our Counter app, using a segemtned control to allow the user to select between either “count by one” or “count by two” modes.

Step 1: Modify the IBActions

The first thing you will need to do is to open up the CounterViewController.h file in Xcode and add an IBAction definition and an integer to store our mode.
Change it to look like this:
  1. #import   
  2.   
  3. @interface CounterViewController : UIViewController {  
  4.     IBOutlet UILabel* countLabel;  
  5.     NSInteger count;  
  6.     NSInteger mode  
  7. }  
  8. @property(nonatomic, retain)UILabel* countLabel;  
  9. @property(nonatomic)NSInteger count;  
  10. @property(nonatomic)NSInteger mode;  
  11.   
  12. - (IBAction)add:(UIButton*)sender;  
  13. - (IBAction)sub:(UIButton*)sender;  
  14. - (IBAction)mode:(UISegmentedControl)sender;  
  15. - (void)displayCount;  
  16.   
  17. @end  
This is a good time to point out that fact that thus far the action definitions in this tutorial have all defined a class-type for sender, which restricts the objects which can call this action to those of that class type. I find this to be a helpful practice because it stops you from connecting things incorrectly. It should be noted, however, that this is not a requirement, these definitions could just as easily have been:
  1. - (IBAction)add:(id)sender;  
  2. - (IBAction)sub:(id)sender;  
  3. - (IBAction)mode:(id)sender;  
Allowing any object to call them. Either way you must make the implementation of these actions match, so open up CounterViewController.m and make these changes:
  1. #import "CounterViewController.h"  
  2.   
  3. @implementation CounterViewController  
  4.   
  5. @synthesize count;  
  6. @synthesize countLabel;  
  7. @synthesize mode;  
  8.   
  9. - (IBAction)add:(UIButton*)sender{  
  10.     switch (mode) {  
  11.         case 0:  
  12.             count++;  
  13.             break;  
  14.         case 1:  
  15.             count += 2;  
  16.             break;  
  17.         default:  
  18.             break;  
  19.     }  
  20.     [self displayCount];  
  21. }  
  22.   
  23. - (IBAction)sub:(UIButton*)sender {  
  24.     switch (mode) {  
  25.         case 0:  
  26.             count--;  
  27.             break;  
  28.         case 1:  
  29.             count -= 2;  
  30.             break;  
  31.         default:  
  32.             break;  
  33.     }  
  34.     [self displayCount];  
  35. }  
  36.   
  37. - (IBAction)mode:(UISegmentedControl)sender {  
  38.     mode = sender.selectedSegmentIndex;  
  39. }  
  40. ...  
  41. @end  
Now we need to modify the interface. So, open up the CounterViewController.xib.
Go over to the library and drag in a segmented control. Now we need to configure it. Make sure the segmented control is selected and open the attributes panel of the inspector. Moving down a little ways under the segment drop-down, which should read “segment 0 – first”, we want to change the title to “One”. Now pull down the segment menu and change to segment “segment 1 – second”, and change its title to “Two”.
Segment Controller View
We also need to connect this to our action. Open up the connections panel and drag from “Value Changed” to the Files Owner. Select the mode “action.”
That’s it. You should now have a counter app that can count up and down by either one or two.

The Toolbar

Thus far the elements we have talked about have numerous possible uses and very few restrictions. The toolbar is the first element we will discuss that has restrictions in the iPhone Human Interface Guidelines. If you plan on using toolbars heavily, you should consult those guidelines, but in short, toolbars should always be placed at the bottom of the interface and they should be composed of buttons with icons no larger than 44px by 44px. It is not a navigational element, and that is an important distinction. If you wish to use it to change view or modes in your app, use a Tab Bar instead. However, if you follow these guidelines than the toolbar is very simple; it is simple a collection of buttons on a bar, and therefore can be used exactly as you would a bunch of buttons. The one difference is that Apple provides a larger set of system presets than they do for standard buttons. You can also place spacers in the toolbar between buttons to change their positions. Let’s try it out.

Step 1: Create the Action

Go back to the the CounterViewController.h and add the following line after your previous action declarations.
  1. - (IBAction)reset:(UIBarButtonItem*)sender;  
Note:
The sender here is a UIBarButtonItem, not a UIToolbar. Each UIBarButtonItem sends it own event, the UIToolbar is simply a container.
Now, add this to your CounterViewController.m, following the actions we defined earlier:
  1. - (IBAction)reset:(UIBarButtonItem*)sender {  
  2.     count = 0;  
  3.     [self displayCount];  
  4. }  

Step 2: Add the Toolbar

Back in IB, let’s drop a UIToolbar from the library onto the view, note that it already has one button on it. To select that button you must double click on it (the first click selects the toolbar, the second selects the button).
Go to the attributes in the inspector. You’ll notice that there are significantly fewer options for a UIBarButtonItem than for other elements. That is due to the fact that toolbars are meant to be uniform, so things like color must be set for the entire toolbar (you can try this out by simply clicking once on the toolbar and then opening the attributes inspector). Change the identifier of the button to “Trash”.
Trash Button
Then connect the button to the reset acton by control dragging to the File’s Owner. If you run your app, you should now be able to rest the count by tapping the trash can.

The Switch

The switch is likely the most restricted element provided by Interface Builder. It has almost no customization options. It has an “On” state and an “Off” state. You can’t change the labels or colors. Switches must always look the same no matter what. Despite the fact that they are very restricted, switches are useful on occasion. For example, settings tend to make heavy use of switches, and the switch can be helpful for turning on and off features in your app -that is exactly what we are going to do. We are going to make a switch that will turn on and off whether we can count negatives in our app.

Step 1: The Code

The first thing to do is make the following modifications to your CounterViewController.h:
  1. #import   
  2.   
  3. @interface CounterViewController : UIViewController {  
  4.     ...  
  5.     Boolean negative;  
  6. }  
  7. ...  
  8. @property(nonatomic)Boolean negative;  
  9. ...  
  10. - (IBAction)negativeSwitch:(UISwitch*)sender;  
  11. ...  
  12. @end  
This simply defines a boolean which will store if we are negative mode or not and an action send by a UISwitch that will change that boolean. So now lets define our action and make the rest of our application respond to our new negative boolean. Modify you CounterViewController.m file to match the following:
  1. #import "CounterViewController.h"  
  2.   
  3. @implementation CounterViewController  
  4. ...  
  5. @synthesize negative;  
  6. ...  
  7. - (IBAction)sub:(UIButton*)sender {  
  8.     switch (mode) {  
  9.         case 0:  
  10.         count--;  
  11.         break;  
  12.   
  13.     case 1:  
  14.         count -= 2;  
  15.         break;  
  16.   
  17.     default:  
  18.         break;  
  19.     }  
  20.   
  21.     if (negative){         //This simply checks if negative mode is off  
  22.         if (count < 0){    //and if count is negative  
  23.             count = 0;     //sets it back to zero  
  24.         }  
  25.     }  
  26.   
  27.     [self displayCount];  
  28. }  
  29. ...  
  30. - (void)viewDidLoad {  
  31.     negative = TRUE;  
  32. }  
  33.   
  34. - (IBAction)negativeSwitch:(UISwitch*)sender {  
  35.     negative = sender.on;  
  36.   
  37.     if (!negative) {  
  38.         if (count < 0) {  
  39.             count = 0;  
  40.             [self displayCount];  
  41.         }  
  42.     }  
  43. }  
All that is being done here is setting the negative mode based on the status of the switch, and then when a subtraction happens checking what mode the switch is currently in (stored in the negative boolean).

Step 2: Inserting a Switch

Switch back to interface builder, find a switch in the library and drop it into the view. Now we need to connect the switch to the action, but in the case of the switch like the segmented control we want to use the Value Changed event, not touch up inside. So go to the connections tab in the inspector, and drag over to the File’s Owner and connect to the negativeMode: action. You may also wish to place a label to mark what the switch does.
Negative Mode
At this point your application should look something like the above.

The Slider

The last and the most complicated element we will discuss is the slider. Sliders represent a range of values(which you can specify), that change as you move along the slider. This element is hugely customizable, but most of these customizations must be done in code and are beyond the scope of this tutorial. We are going to use it to make a multiplier and divider for our counter.

Step 1: Code it Up

The first thing we need, is, yup you guessed it, another action. Add the following to the CounterViewController.h with the rest of your action declarations:
  1. - (IBAction)multiplier:(UISlider*)sender;  
Next we need to implement the multiplication and division function for our counter so modify your CounterViewController.m like so:
  1. #import "CounterViewController.h"  
  2.   
  3. @implementation CounterViewController  
  4. ...  
  5. @synthesize mult;  
  6. ...  
  7.   
  8. - (IBAction)add:(UIButton*)sender{  
  9.     count +=mode;  
  10.   
  11.     count *= mult;  
  12.   
  13.     if (!negative) {  
  14.         if (count < 0) {  
  15.             count = 0;  
  16.         }  
  17.     }  
  18.   
  19.     [self displayCount];  
  20. }  
  21.   
  22. - (IBAction)sub:(UIButton*)sender {  
  23.     count -= mode;  
  24.   
  25.     count /= mult;  
  26.   
  27.     if (!negative) {  
  28.         if (count < 0) {  
  29.             count = 0;  
  30.         }  
  31.     }  
  32.   
  33.     [self displayCount];  
  34. }  
  35.   
  36. - (IBAction)mode:(UISegmentedControl*)sender {  
  37.     mode = sender.selectedSegmentIndex+1;   //Don't forget to add the +1 here  
  38. }  
  39.   
  40. - (IBAction)multiplier:(UISlider*)sender {  
  41.     mult = sender.value;  
  42. }  
  43. ...  
  44. - (void)viewDidLoad {  
  45.     negative = TRUE;  
  46.     mult=1;  
  47. }  
  48. ...  
  49. @end  
Now when you add or subtract the number is multiplied or divided by the value of the slider. If the slider is at 1 (which will be the lower limit) the counter acts normally at 9 (which will be the maximum).

Step 2: Create a Slider

Back in IB, grab and drop a slider from the library into the view, and open its attributes in the inspector. The first thing you should notice here are the values. We want to change them a bit. As mentioned earlier, you want the minimum value to be 1, the maximum value to be 9, and the initial value to be 1. Uncheck the continuos box so that we don’t get any decimal point in there and that’s it. Just connect the “value changed” event of your slider to the File’s Owner and you’ve got your multiplier!
Your final app should look something like the one displayed below:
Final Preview

Conclusion

This tutorial has barely scratched the surface of what is possible in Interface Builder. It is an extremely powerful application. Today, we have covered the basic usage of IB and the most basic elements provided in the IB library. This tutorial has shown how you can create a fully functional application, using Interface Builder, without very much code. Always remember to consult the iPhone Human Interface Guidelines before doing anything drastic, and for more interface inspiration and assistance be sure to check Apple’s UICatalog.

Comments