iPhone Application Development : Creating a Multi-View Toolbar Application (part 3) - Adding Toolbar Controls

2/28/2011 11:02:15 AM

Adding Toolbar Controls

The MultipleViews application that we’re building now requires a single toolbar with buttons for each of the three views that we want to display. The toolbar itself will be added as a subview of the view in the MultipleViewsViewController.xib file.

If you haven’t already, open the MultipleViewsViewController.xib file in Interface Builder. The view contained in this XIB file, as you know from previous view-based applications, is what will be added to the application’s window when it first launches. Instead of providing all of the onscreen content, however, we just want this view and its view controller to manage the toolbar and the user’s interactions with it.

Open the view and, using the Library objects (Tools, Library), drag an instance of a toolbar (UIToolbar) to the bottom of the view. You should now have an empty view with a single-button toolbar visible.

Adding and Editing Toolbar Buttons

We will need three buttons for this project. Drag a bar button item (UIBarButton) from the Library to the toolbar. An insertion point will appear where the button will be added. Repeat this process until there are a total of three buttons (one for each view) in the toolbar.

Double-click the button’s title to switch to an editable mode. Edit each button title to correspond to one of the views that needs to be displayed: First View, Second View, Third View.

Did you Know?

If you have difficulty selecting the buttons directly in the layout view, you may also select them using the Document window and edit their titles by accessing the Attributes Inspector (Command+1).

After editing the titles, you may want to resize the buttons to create a uniform appearance in the toolbar. You can use the Size Inspector (Command+3) to adjust the width numerically, or just click and drag the resize handle that appears to the right of the currently selected button.

The end result should resemble Figure 8.

Figure 8. The final toolbar should contain three buttons with appropriate titles.

By the Way

Bar button items do not have to be text-labeled buttons. Alternatively, you can set an image file to be used as the button representation in the Attributes Inspector. We will be using this feature of the tab bar UI element in the next project.

Adding Outlets and Actions

Now that all the interface elements are in place for the MultiViews application, we need to connect them to code. The MultiViewsViewController object will handle the switching of the views, so we need to edit the class to include outlets for each of the view controllers, as well as actions for each of the toolbar buttons, and a new method clearView that we’ll use to clear the contents of the view as we switch between them.

Edit MultipleViewsViewController.h to reflect the code in Listing 1.

Listing 1.
 1: #import <UIKit/UIKit.h>
3: @class FirstViewController;
4: @class SecondViewController;
5: @class ThirdViewController;
7: @interface MultipleViewsViewController : UIViewController {
8: IBOutlet FirstViewController *firstViewController;
9: IBOutlet SecondViewController *secondViewController;
10: IBOutlet ThirdViewController *thirdViewController;
11: }
13: @property (retain, nonatomic) FirstViewController *firstViewController;
14: @property (retain, nonatomic) SecondViewController *secondViewController;
15: @property (retain, nonatomic) ThirdViewController *thirdViewController;
17: -(IBAction) loadSecondView:(id)sender;
18: -(IBAction) loadThirdView:(id)sender;
19: -(IBAction) loadFirstView:(id)sender;
21: -(void) clearView;
23: @end

Let’s quickly run through what we’ve done here. Because this class needs to be aware of our other view controller classes, we first declare the view controller classes in lines 3–5.

Lines 8–10 create IBOutlets for each of our view controller instances (firstViewController, secondViewController, and thirdViewController); we’ll need to access them to switch between views.

In lines 13–15, we declare these three instances as properties.

Lines 17–19 declare three methods for switching views and expose them as IBActions for Interface Builder (loadFirstView, loadSecondView, and loadFirstView).

Finally, on line 21, a new method, clearView, is declared. It will be used to remove the old content from our view when we switch to a new view.

Connecting Outlets and Actions

Save the changes you’ve made to MultiViewsViewController.h, and jump back into the MultiViewsViewController.xib file in Interface Builder. We can now make our final connections before writing the view switching code.

From the Document window, Control-drag from the File’s Owner icon to the instance of FirstViewController. When prompted for an outlet, choose firstViewController, as shown in Figure 9.

Figure 9. Connect each view controller to its outlet within the MultipleViewsViewController class.

Repeat this process for the secondViewController and thirdViewController instances, choosing the appropriate outlet when prompted.

Next, expand the view and toolbar hierarchy to show the three bar button items that we added earlier. Control-drag from the First View button to the File’s Owner icon. When prompted, choose the loadFirstView sent action.

Do the same for the two other buttons, connecting the Second View button to loadSecondView and the third to loadThirdView. The interface connections are now complete, and we can finish up the implementation of the view loading methods.

Implementing the View Switch Methods

To implement the view switching, we’ll be making use of a UIView instance method called insertSubview:atIndex:. This method inserts a view as a subview of another view—just like creating a hierarchy of views within Interface Builder. By inserting a subview at an index of 0 into the view containing our toolbar, we will effectively “float” the toolbar view on top of the subview.

Begin the implementation by opening MultipleViewsViewController.m in Xcode. Import the headers from the three view controller classes so that we can properly access them in the code:

#import "MultipleViewsViewController.h"
#import "FirstViewController.h"
#import "SecondViewController.h"
#import "ThirdViewController.h"

Next, after the @implementation directive, use @synthesize to create the getters and setters for the view controller instances (firstViewController, secondViewController, thirdViewController):

@synthesize firstViewController;
@synthesize secondViewController;
@synthesize thirdViewController;

Create the method to load the first view, loadFirstView, as follows:

-(IBAction) loadFirstView:(id)sender {
[self.view insertSubview:firstViewController.view atIndex:0];

This single line of code uses the insertSubview:atIndex: method of the MultiViewsViewController’s view instance (which contains our toolbar!) to add a subview that will appear below it. That’s all there is to it!

Following this pattern, implement the loadSecondView and loadThirdView methods to insert their respective view controller’s views as subviews to the toolbar view.

By the Way

If you’re confused why self.view is the view containing the toolbar, look at the structure of the project and the XIB files. We’re adding the loadView methods to the MultiViewsViewController class, so self refers to the instance of that class. The MultiViewsViewController has a single view with a toolbar that we added earlier, so self.view, within this context, is just a reference to that view.

After you’ve finished the view loading implementation, don’t forget to release the view controllers in the dealloc method:

- (void)dealloc {
[firstViewController release];
[secondViewController release];
[thirdViewController release];
[super dealloc];

Setting a View When the Application Starts

If you try to run the application now, it should work, but it probably won’t do quite what you may expect. When the application first starts, it loads the initial view containing the toolbar but nothing else. Until a toolbar button is pressed, none of our three content views are visible. A much more user-friendly approach is to automatically load content as soon as the application starts.

To automatically switch to one of the views, we can simply use one of the loadView methods that we just defined.

Editing MultipleViewsViewController.m, implement the viewDidLoad method as follows:

- (void)viewDidLoad {
[self loadFirstView:nil];
[super viewDidLoad];

By calling the loadFirstView: method upon successful loading of the view containing the toolbar, we ensure that some initial content is available for users without them first having to press any buttons.

By the Way

Because loadFirstView is defined as requiring a parameter in its implementation, we must pass a parameter when using it here. Because the parameter (sender) is not used in the function, we can safely pass nil with no ill effects.

Clearing the Current View

Try building and executing the application again. This time, an initial view should load, but the application still won’t perform correctly. You’ll likely see sporadic behavior as you try to navigate between views or the views will overlay on top of one another, creating an onscreen mess. The problem is that while we’re adding subviews as the toolbar button is pressed, we’re never removing them again! What we need to do to stabilize the application’s behavior is to identify and remove the current subview each time the toolbar button is pressed.

When a view is added to another as a subview (its superview), a property called superview is set appropriately. In other words, when firstViewController.view is added as a subview to our toolbar view, its superview property is set to the toolbar view. If a view hasn’t been added as a subview, the property is nil. So, how can this help us? Easy: By testing to see whether the superview property is set, we can identify which view has been made active and then remove it when it’s time to switch views. To remove a view from its superview, we can use the removeFromSuperview instance method.

Add the clearView method shown in Listing 2 to MultipleViewsViewController.m.

Listing 2.
-(void) clearView {
if (firstViewController.view.superview) {
[firstViewController.view removeFromSuperview];
} else if (secondViewController.view.superview) {
[secondViewController.view removeFromSuperview];
} else {
[thirdViewController.view removeFromSuperview];

In this implementation, we test for the existence of the superview property in all of the view controller’s views and, if we find it, we use removeFromSuperview to remove the view.

All that remains is to add clearView so that it is called before any view is loaded. A completed version of the loadFirstView method is shown in Listing 12.3.

Listing 3.
-(IBAction) loadFirstView:(id)sender {
[self clearView];
[self.view insertSubview:firstViewController.view atIndex:0];

Make the same change to loadSecondView and loadThirdView, and then retest your application. It should now cleanly switch between the different views by touching the toolbar buttons, as shown in Figure 10.

Figure 10. Switch between views using the toolbar buttons.

  •  Windows Phone 7 Development : Using Location Services - Simulating the Location Service
  •  Introducing the Windows Phone Location Service and Mapping APIs
  •  iPhone Application Development : Implementing a Custom Picker View (part 4) - Tweaking the Picker UI
  •  iPhone Application Development : Implementing a Custom Picker View (part 3) - Reacting to a Picker View Choice
  •  iPhone Application Development : Implementing a Custom Picker View (part 2)
  •  iPhone Application Development : Implementing a Custom Picker View (part 1)
  •  Windows Phone 7 Development : Isolated Storage - Working with Isolated Storage Settings
  •  Mobile Application Security : WebOS Security - Permissions and User Controls
  •  Mobile Application Security : WebOS Security - Code Security
  •  Windows Phone 7 Development : Working with Isolated Directory Storage (part 2)
  •  Windows Phone 7 Development : Working with Isolated Directory Storage (part 1)
  •  iPhone Application Development : Making Multivalue Choices with Pickers - Using Date Pickers (part 3)
  •  iPhone Application Development : Making Multivalue Choices with Pickers - Using Date Pickers (part 2) - Adding a Date Picker
  •  iPhone Application Development : Making Multivalue Choices with Pickers - Using Date Pickers (part 1)
  •  iPhone Application Development : Making Multivalue Choices with Pickers - Understanding Pickers
  •  Sync Your iPad with iTunes : Troubleshooting iTunes and the Sync
  •  Sync Your iPad with iTunes : Manually Transferring Music, Movies, Podcasts, and More on Your iPad (Drag-and-Drop Method)
  •  Windows Phone 7 Development : Internationalization - Using Resource Files to Localize Content
  •  Windows Phone 7 Development : Internationalization - Storing and Retrieving Current Culture Settings
  •  Mobile Application Security : WebOS Security - Development and Security Testing
    Top 10
    Canon EOS 6D - A Beginner-Friendly Full-Frame Camera
    Fujifilm FinePix F800EXR - A Versatile Camera With Wireless Connectivity
    8 Essential Free Apps – Q1 2013
    Your First Steps - Start Your Windows Journey Here
    Asus Zenbook Prime UX31A Touch Review - New Touchscreen And Equally Stable Performance (Part 2)
    Asus Zenbook Prime UX31A Touch Review - New Touchscreen And Equally Stable Performance (Part 1)
    Dell XPS 13 - Look, Don't Touch
    HTC Butterfly - Transform The Way You See And Hear The World
    HTC Desire SV Review – A Shining Mid-Range Dual-SIM Smartphone
    Lenovo K860 - Android Smartphone
    Most View
    Apple iPhone 5 - The World’s Best Smartphone? (Part 2)
    Using System Support Tools in Vista
    ADO.NET Programming : Microsoft SQL Server CE (part 4) - Updating a SQL Server CE Database, The SqlCeDataAdapter Class
    Cloud Computing : Controlling It All with Web-Based Desktops - Evaluating Web-Based Desktops
    Instagram Substitutes On Android (Part 1) - Streamzoo, Flickr & PicPlz
    Managing Exchange Server 2010 : Archiving and compliancy (part 2) - Messaging Records Management
    Exchange Server 2007 : Work with Remote Domains
    B&W 800 Diamond
    300Mbps AV200 Wireless N Powerline Extender TL-WPA281
    Silverlight : Data Binding - Providing reasonable defaults for bound data
    The choices of mobile computing for SOHO users (part 2)
    ASP.NET 4 in VB 2010 : ADO.NET Fundamentals (part 1) - Understanding Databases, Configuring Your Database
    Windows Vista : Performing Local PC Administration (part 2) - Performing common workstation administration tasks
    Samsung Galaxy Ace 2 Reviews (Part 1)
    Programming Role-Based Security
    Accutone Pisces Band Headphones - Clear And Discrete Sound
    Blackberry World 2012 (Part 2) - BlackBerry 10, Apps and development
    The Future Of Apple: Chip Off The Block (Part 2)
    Adobe's Creative Suite Dreams
    All the stuff you didn't know (Part 3)