iPhone Application Development : Building a Multi-View Tab Bar Application (part 2) - Implementing the Area View

3/19/2011 4:35:22 PM

Configuring the View Controller Classes

The next step before we start coding is to set the view controller instances we’ve added to the tab bar controller so that they point to the AreaViewController, VolumeViewController, and SummaryViewController classes and their related views (AreaView, VolumeView, and SummaryView).

Select the first view controller icon in the MainWindow.xib. (It should contain the Area tab bar item.) Open the Identity Inspector (Command+4) and use the Class drop-down to choose AreaViewController. Without closing the inspector, switch to the Attributes view (Command+1) and use the NIB Name drop-down to select the AreaView XIB. Set the view controller classes and NIBs for the other two view controller instances in the project.

Implementing the Area View

Although we haven’t really written any code specific to switching views or managing view controllers, the TabbedCalculation application can be built and executed and will happily switch views using the tab bar. No need for inserting subviews or clearing views. It just works!

We can now work with our view controller classes just as we would in any other application. The tab bar controller instance will take care of swapping the views when needed. We’ll start with the area calculation view.

Adding Outlets and Actions

In the area view, the application will calculate the area of a rectangle given the length and width, and the area of a circle, given the radius. We’ll need UITextFields for each of these values, and two UILabel instances for the calculation results.

The view controller will need to access the instance of the SummaryViewController to increment a count of the calculations performed. It will provide calculate and hideKeyboard methods to perform the calculation and hide the input keyboard when the background is tapped, respectively. All told, we’ll need six IBOutlets and two IBActions. These are the naming conventions we’ve used in the sample project:

rectWidth (UITextField): Field for entering the width of a rectangle

rectLength (UITextField): Field for entering the length of a rectangle

circleRadius (UITextField): Field for entering the radius of a circle

rectResult (UILabel): The calculated area of the rectangle

circleResult (UILabel): The calculated area of the circle

summaryViewController (SummaryViewController): The instance of the Summary view

calculate (method): Performs the area calculation

hideKeyboard (method): Hides the onscreen keyboard

Got all that? Good! Within Xcode, open the AreaViewController.h header file and edit the contents to read as shown in Listing 2.

Listing 2.
 2: #import "SummaryViewController.h"
4: @interface AreaViewController : UIViewController {
5: IBOutlet UITextField *rectWidth;
6: IBOutlet UITextField *rectLength;
7: IBOutlet UITextField *circleRadius;
8: IBOutlet UILabel *rectResult;
9: IBOutlet UILabel *circleResult;
10: IBOutlet SummaryViewController *summaryViewController;
11: }
13: @property (retain, nonatomic) UITextField *rectWidth;
14: @property (retain, nonatomic) UITextField *rectLength;
15: @property (retain, nonatomic) UITextField *circleRadius;
16: @property (retain, nonatomic) UILabel *rectResult;
17: @property (retain, nonatomic) UILabel *circleResult;
19: -(IBAction)calculate:(id)sender;
20: -(IBAction)hideKeyboard:(id)sender;
22: @end

We’ll need to access a method within the SummaryViewController instance, so, in line 2, we import the header for the summary class. Lines 5–10 declare the outlets for the fields, labels, and Summary view controller. Lines 13–17 then declare these as properties. Finally, lines 19–20 declare two IBActions that we’ll be triggering based on Touch Up events in the interface.

Creating the View

Based solely on the code, you should be able to get a pretty good sense for what the view is going to look like. The finished version of our sample AreaView is shown in Figure 5.

Figure 5. Create inputs, outputs, and a Calculate button!

Notice that we’ve included two images (UIImageView) in sample application view. These serve as cues for users so that they understand what is meant by length, width, radius, and so on (hey, you never know!). If you want to add these to your version of the application, drag the CircleArea.png and RectArea.png files to your Xcode Resources folder. You can also add the SphereVolume.png and BoxVolume.png images, which are used in the volume view.

Now it’s your turn to build the view. Open AreaView.xib, and begin by dragging three instances of UITextField to the view. Two should be grouped together for the length and width entry for a rectangle; the third will be for the radius. After you’ve added the fields to the view, select each and open the Attributes Inspector (Command+1). Set the text field traits so that the keyboard is set to a number pad, as shown in Figure 6.

Figure 6. Because we need only numeric input, set the keyboard to be a number pad.

Drag instances of UILabel to the view and use them to label each of the fields.

The results of the area calculations need to be displayed near the entry fields, so add two additional UILabel instances to the view—one located near the fields for the rectangle, the other near the radius field. Double-click to edit and clear their contents, or set them to 0 as the default. Use two more UILabels to create Area labels. Visit all the labels and fields with the Attributes Inspector (Command+1) and set a size that is appropriate for the iPhone screen.

If you’d like to add the images to the view, add two image views from the library, positioning one beside the rectangle fields, the other beside the radius fields. Open the Attributes Inspector (Command+1) for each image view and choose the RectArea.png or CircleArea.png images.

To finish the view, we need two buttons. Add the first button to the bottom of the view and name it Calculate. The second button traps background touches and triggers the hideKeyboard method. Add a button that spans the entire background. Use the Layout menu to send it to the back, or drag its icon into the Interface Builder Document window so that it falls at the top of the View hierarchy. Open the Attributes Inspector (Command+1) for the button and choose Custom for the button type to make the button invisible, as demonstrated in Figure 7.

Figure 7. Set a Custom button type for the large background button.

When you’ve finished with the view layout, you’ll have quite a few objects in the hierarchy. If you expand the Document window, it should resemble what we’ve created in Figure 8.

Figure 8. There are quite a few objects in the view.

Connecting Outlets and Actions

After creating an appropriate user interface for the area view, connect the objects to the instance variables that we defined earlier. Control-drag from the File’s Owner icon to each of the three UITextField instances. When prompted, create the connection from the field to the correct variable.

Assign rectResult and circleResult by Control-dragging from the File’s Owner icon to the two UILabels that will hold the results for the area calculations.

For the two buttons, Control-drag from the button to the File’s Owner icon. Set calculate as the event for the Calculate button, and hideKeyboard for the custom background button.

Implementing the Area Calculation Logic

We have our inputs, our outputs, and a trigger for the calculate method. Let’s tie them together to finish up the area view. Switch back to Xcode and edit the AreaViewController.m file.

Although it isn’t quite necessary for a project this size, defining constants for commonly used values can be helpful in creating readable code. With this in mind, define a constant, Pi, near the top of the file. We’ll use this in the calculation of the circle’s area:

#define Pi 3.1415926

Next, after the @implementation directive, synthesize the getters/setters for all of the properties defined in the header file:

@synthesize rectWidth;
@synthesize rectLength;
@synthesize rectResult;
@synthesize circleRadius;
@synthesize circleResult;

Now for the real work—implementing the calculate method. Add the method definition shown in Listing 3 to the class.

Listing 3.
 1: -(IBAction)calculate:(id)sender {
2: float floatRectResult=[rectWidth.text floatValue]*
3: [rectLength.text floatValue];
4: float floatCircleResult=[circleRadius.text floatValue]*
5: [circleRadius.text floatValue]*Pi;
6: NSString *stringRectResult=[[NSString alloc]
7: initWithFormat:@"%1.2f",floatRectResult];
8: NSString *stringCircleResult=[[NSString alloc]
9: initWithFormat:@"%1.2f",floatCircleResult];
10: rectResult.text=stringRectResult;
11: circleResult.text=stringCircleResult;
12: [stringRectResult release];
13: [stringCircleResult release];
15: [summaryViewController updateTotal];
16: }

We’re working with the assumption that you’re comfortable with the equations for calculating the area of a rectangle (l*w) and a circle (Pi*r^2), but a few pieces of the code might be unfamiliar. Lines 2–3 and 4–5 calculate the area for the rectangle and circle, respectively, and store the results in two new floating point variables (floatRectResult, floatCircleResult). The calculations take advantage of the NSString class method floatValue to provide a floating-point number from the user’s input.

By the Way

The floatValue method will return 0.0 if the user types in gibberish. This means we always have a valid calculation to perform, even if the user enters bad information.

Lines 6–7 and 8–9 allocate and initialize two strings to hold the formatted results. Using initWithFormat: and the format "%1.2f” to create the strings, we ensure that there will always have at least one digit before the decimal and two decimal places in the result.

Lines 10–13 set the results within the view and then release the temporary strings. The last step, in line 15, uses an instance method of the SummaryViewController, updateTotal, to update the total number of calculations performed. Defining this method will be one of the last things we do this hour.

All in all, the calculation logic isn’t difficult to understand. The only pieces missing are the implementation of hideKeyboard and releasing our objects in dealloc. Go ahead and define hideKeyboard as follows:

-(IBAction)hideKeyboard:(id)sender {
[rectWidth resignFirstResponder];
[rectLength resignFirstResponder];
[circleRadius resignFirstResponder];

Wrap up the implementation of the area view controller by editing dealloc to release the objects we used:

- (void)dealloc {
[rectWidth release];
[rectLength release];
[circleRadius release];
[rectResult release];
[circleResult release];
[super dealloc];

AreaViewController and AreaView are complete. Building the volume view and view controller will follow a very similar process, so we’ll move quickly through the next section.

  •  iPhone Application Development : Building a Multi-View Tab Bar Application (part 1)
  •  Windows Phone 7 Development : Working with Video (part 2) - Coding the Application
  •  Windows Phone 7 Development : Working with Video (part 1)
  •  Windows Phone 7 Development : Plotting an Address on a Bing Maps Map and Working with the Bing Maps Service
  •  Windows Phone 7 Development : Using GeoCoordinateWatcher and the Bing Maps Control to Track Your Movements
  •  iPhone Application Development : Creating a Multi-View Toolbar Application (part 3) - Adding Toolbar Controls
  •  iPhone Application Development : Creating a Multi-View Toolbar Application (part 2) - Instantiating the View Controllers
  •  iPhone Application Development : Creating a Multi-View Toolbar Application (part 1)
  •  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)
    Top 10
    Security Policy Explained in .NET
    Windows Server 2008: Defining AD Groups
    Building Android Apps: Web SQL Database (part 3) - Selecting Rows and Handling Result Sets
    Automating Blind SQL Injection Exploitation
    ASP.NET 4 : Getting More Advanced with the Entity Framework (part 1) - Querying with LINQ to Entities
    Algorithms for Compiler Design:
    Windows 7 : Maintaining Your System Configuration (part 3) - Configuring User Profiles, Environment Variables, and Startup and Recovery
    Examining Exchange Server 2010 Performance Improvements
    Mixing Windows and Forms
    Windows 7 : Using Desktop Gadgets (part 3) - Using the Stock, Currency, Slide Show gadget
    Most View
    Windows 7 : Using the Windows Backup Program
    Microsoft XNA Game Studio 3.0 : Controlling Color (part 2)
    Implement an Observer (aka Subscriber) Pattern
    Monitoring a SharePoint 2010 Environment : Understanding Timer Jobs for SharePoint 2010
    Programming the Mobile Web : Widgets and Offline Webapps - Standards
    Understanding Mobility Enhancements in Exchange Server 2010
    iPhone Programming : Simplifying the Template Classes
    SQL Azure : Managing a Shard (part 2) - Working with Partial Shards
    Windows Server 2008 : Domain Name System and IPv6 - DNS in Windows Server 2008 R2
    SQL Server 2008 : Programming Objects - Implementing Triggers
    Windows Azure : Common uses for worker roles (part 2) - State-directed workers
    Understanding Snapshot Isolation
    Optimizing Toolbars in Vista
    Using Group Policy in Windows Vista
    Programming .NET Security : Asymmetric Encryption Explained (part 2) - Creating the Encrypted Data
    Managing Exchange Server 2010 : The Exchange Management Shell (part 1) - Bulk user creation in the Exchange Management Shell
    Finite Automata and Regular Expressions
    Synching an On-Premises Database with SQL Azure
    Exploring the T-SQL Enhancements in SQL Server 2005 : Ranking Functions
    SQL Azure: Building a Shard (part 1) - Designing the Shard Library Object