Where This Tutorial Comes From

I have for this article started from an earlier version of the Apple provided tutorial entitled "ObjCTutorial" which can be found on Apple's Developer Connection. I recommend you work through this tutorial at some stage as it gives a good introduction to object oriented programming and explains, among other things, the syntax of Objective-C. It constructs a currency conversion application where the user enters an exchange rate and an amount of money and the program returns the value in the other currency. You may find, as I did, some sections made confusing by typographical errors. In my version presented in this article, I have chosen a simpler example - area of a circle - which requires only one user input value (radius). I acknowledge my indebtedness to the authors of that tutorial. Before starting I should point out that I am a newcomer to Objective-C and have written this article primarily to help consolidate what I am learning as I go through some of the tutorials and sample code. I should also point out that I was running Mac OS X Version 10.2. You may find differences if using a later version. I have broken down the process of building the application into many small numbered steps allowing you to keep track of where you have got to and where you have found problems. Let's get started on writing an Objective-C application.

Start Project Builder Application

To open Project Builder and start a new project:
1. Find Project Builder in /Developer/Applications
2. Drag the Project Builder icon to the Dock for later use.
3. Double-click the Project Builder icon.
4. If this is the first time you start Project Builder, you'll be asked a few setup questions. Accept the default values.
5. Choose New Project from the File menu.
6. Select Cocoa Application in the Assistant dialogue and then click Next.
7. In the Project Name field type "AreaOfCircle".
8. Click Choose and navigate to your "Programming In OSX" folder.
9. Click Finish. Project Builder creates and displays a project window.

Sorry No Image
Fig 2 Starting a new Cocoa Application project in Project Builder

Click on some of the arrows in the Groups & Files panel at the left of the window. In particular note these:Classes: This group is empty at first, but it will later be used to hold the implementation and header files for the project. Resources: This group contains the nib files (extension .nib) and other resources which specify the application's user interface. (The name "Nib" comes from Next and Interface Builder).

Start Interface Builder Application

Now open the Main Nib File:
10. Locate MainMenu.nib in the Resources group in Project Builder.
11. Double-click to open it. This will open Interface Builder and bring up the nib file. A default menu bar and window titled "Window" will appear when the nib file is open.

Rename The Window

12. Click on the Window and choose Show Info from the Tools menu.
13. Select Attributes from the pop up menu of the Info panel.
14. Change Window Title from Window to "Area Of Circle".
15. Verify that the 'Visible at launch time' option is selected.
16. De-select the Zoom (and resize) check box in the Title Bar Controls area. Save the Interface Builder File and remember to save regualrly as you proceed through the project.

Resize The Window

You can resize the window by dragging the lower right corner or more precisely by using the Size menu of the Window Info Window.
17. Select Size from the pop-up menu.
18. In the Content Rect area, select Width/Height from the right-hand pop-up menu. Type 400 in the width (w) field and 200 in the height (h) field.

Place a Text Field, Resize and label It

19. Drag a text field object (NSTextField) from the Cocoa Text pallet on to the Area Of Circle window. Use the blue guide-lines that appear sometimes to help you drag the field into position.
20. Resize the text field by grabbing the left handle and dragging to the left to enlarge the text field.
21. Drag a System Font Text object onto the window from the Cocoa Views palette, again using the guide-lines to locate it at the left of the text field.
22. Double click to select the System Font Text label and change it to "Radius of the Circle".

Sorry No Image
Fig 3 View of renamed window with one labelled text field

Make Another Labeled Text Field

23. Shift click to select both objects in the window - the text field and the label. Then choose Duplicate from the Edit Menu. Taking heed of the blue guide-lines, drag the copy into position below the originals.
24. Double click the new label and change it to "Area of the Circle".
25. Select the new text field on its own. Under the Attributes window deselect the Editable checkbox.

Sorry No Image
Fig 4 Contents of second text field will not be editable

Add a Button

Now we will add a Button to invoke the area calculation. We will set it up so that the calculation will be done when the user clicks the button or presses Return.
26. Drag the button object from the Cocoa Controls palette and put it in the lower-right portion of the window.
27. Double click the title of the button to select its label and change it to "Circle Area".
28. Choose Attributes in the NSButton Info Window, and then choose Return from the pop-up menu labeled "Equiv:".
29. Align the button under the text fields. (Another help is available for alignment: Select the button and, without clicking, move the mouse pointer to a clear area in the window. Then press Option to see how far the button is from the window boundaries and other objects.)
30. Resize the window to be as small as the guidelines will allow.

Sorry No Image
Fig 5 The finished Area Of Circle window

Testing The Interface

31. From the File Menu choose Test Interface. You should be able to enter text into the first box and edit, copy and paste it. Test the effect of pressing Return - the button should highlight briefly. When you finish testing, Quit from Test Interface and Save. You have now completed the layout of the user interface. The next task is to connect the text fields and the button to parts of the program.

Specify a Subclass

The parent of all objects in Cocoa is the class called NSObject. We will define a subclass of NSObject as the controller object in our program and we will call this subclass CircleAreaController. As a subclass of NSObject our object will inherit many useful methods and variables.
32. In Interface Builder, select the Classes tab of the MainMenu.nib window.
33. From the drop down list choose NSObject as shown in the picture.

Sorry No Image
Fig 6 Classes tab has been selected and NSObject is being chosen

34. In the left-most column click on NSObject and hit Return to create an NSObject subclass called "MyObject." Type "CircleAreaController" to rename it. The new class CircleAreaController will coordinate events and flow of messages between the user interface and another class we will create to carry out the calculation.

Create Three Outlets for our CircleAreaController subclass

35. Select CircleAreaController in the Classes window.
36. Choose 'Add Outlet to CircleAreaController' from the Classes menu.
37. Change the name of this outlet from myOutlet to "radiusField".
38. Repeat to create the second outlet and name it "areaField".

Sorry No Image
Fig 7 After making the radiusField outlet, create another outlet called areaField

The CircleAreaController subclass is able to access the two text fields of the interface via the outlets just created. But CircleAreaController must also communicate with another subclass we will call 'Calculate' (yet to be defined) which will actually do the A = pi r squared calculation.
39. Create the third outlet and name it "calculateFormula". Note again that the CircleAreaController subclass communicates with the text fields via the radiusField and areaField outlets. On the other hand CircleAreaController communicates with the Calculate object via the calculateFormula outlet.

Define the Actions of the Class

CircleAreaController has one action method that we will name 'calculate:'. When the user clicks the Circle Area button, a calculate: message is sent to the target object, an instance of CircleAreaController. We must create an action for our subclass CircleAreaController.
40. Select CircleAreaController in the Classes window.
41. Choose 'Add Action to CircleAreaController' from the Classes menu.
42. Change the name of this action from myAction to "calculate". You should now check that you have three outlets and one action for our subclass CircleAreaController. The outlets are areaField, calculateFormula and radiusField (all of Type id). The one action is calculate:.

Generate an Instance of the CircleAreaController Class

As the final step of defining a class in Interface Builder, you create an instance of your class and connect its outlets and actions.
43. Select CircleAreaController in the Classes window.
44. Choose 'Instantiate CircleAreaController' from the Classes menu. The instance will appear in the Instances view as shown highlighted in the next picture.

Sorry No Image
Fig 8 The (blue) box shape represents an instance of the CircleAreaController class

Connect the Instance to its two Outlets via the Aqua interface

Now you can connect this CircleAreaController object to the user interface. By connecting it to specific objects in the interface, you initialize its outlets. CircleAreaController will use these outlets to get and set values in the interface.
45. In the Instances display of the nib file window, Control-drag a connection line from the CircleAreaController instance to the first text field, as shown in the next picture. When the text field is outlined, release the mouse button. The direction of connection is important. In this case start at the instance and drag to the text field.

Sorry No Image
Fig 9 Control-drag from the CircleAreaController instance to the first text field

46. Interface Builder brings up the Connections display of the Info window. Select the outlet that corresponds to the first field (radiusField) and click the Connect button.
47. Following similar steps, connect CircleAreaController's areaField outlet to the second text field.If you get a connection wrong just select the outlet and click the Disconnect button.

Connect the Instance to its Action

Connect the Interface Controls (the Circle Area Button) to the Class's Actions (calculate:). In this case the connection starts at the button and connects to the CircleAreaController Instance.
48. Control-drag a connection from the Circle Area button to the CircleAreaController instance in the nib file window. When the instance is outlined, release the mouse button.
49. In the Connections display, make sure 'target' in the Outlets column is selected.
50. Select 'calculate:' in the Actions column.
51. Click the Connect button. Save again.

Sorry No Image
Fig 10 Path of the calculate: action is from the button to the CircleAreaController instance

Define the Calculate Class:

While connecting CircleAreaController's outlets, you probably noticed that one outlet remains unconnected: 'calculateFormula'. This outlet identifies an instance of the Calculate class in the AreaOfCircle application, but this instance doesn't exist yet. This class does not communicate directly with the Aqua graphic interface so there is no need for outlets or actions. Here are the steps to be followed to create a new subclass called Calculate.
52. In the Classes display, make Calculate a subclass of NSObject. (Select NSObject and choose 'Subclass NSObject' from the Classes Menu and rename it 'Calculate' with a capital C.)
53. Instantiate the Calculate class. (Select the Calculate subclass and choose 'Instantiate Calculate' from the Classes menu.)
54. Make an outlet connection between CircleAreaController and Calculate. ( Control-drag from the CircleAreaController instance to the Calculate instance which is right next to it in the same window. While the yellow connecting line is visible, click on 'calculateFormula' in the connections window and then click Connect.
55. Save MainMenu.nib. Just to check everything is connected correctly, select the instance of CircleAreaController in the Instances window with the Info window set on Connections. Check that the three outlets in the left column have dots against them. As you select each outlet in turn the yellow connection lines show up between the instance and the user Interface window. The small filled yellow square indicates the source of messages and the larger unfilled yellow square represents the destination.

Sorry No Image
Fig 11 Each of the three outlets displays a dot. Select each outlet in turn to see its connections

Generate the Source Files

Interface Builder is now able to generate the source code for the two subclasses of NSObject - CircleAreaController and Calculate.
56. Go to the Classes display of the nib file window.
57. Select the CircleAreaController class.
58. Choose 'Create Files for CircleAreaController' in the Classes menu.
59. Verify that the check boxes in the Create column next to the .h and .m files are selected.
60. Verify that the check box next to "Insert into AreaOfCircle" is selected.
61. Click the Choose button.
62. Repeat the above steps to generate the source code for the Calculate class.
63. Save the nib file.Now hide (Command-H) Interface Builder as it is not required further for this application. You will complete constructing the application using Project Builder.

Examine an Interface (header) File in Project Builder

There are four new files (created by Interface Builder) showing in the left panel Groups & Files. They are CircleAreaController.h, CircleAreaController.m, Calculate.h and Calculate.m. They may not be in the correct place - if they are not in the Classes group just drag them there.
64. Click Project Builder's main window to activate it.
65. Select all four files in the project browser and drag them into the Classes group.

Declare the calculateTheArea: method in the header file.

This is where we insert a method into the Calculate class that the CircleAreaController object can invoke to get the result of the computation of the circle area. Let's start by declaring the method in Calculate.h.
66. Select Calculate.h in the project browser.
67. Insert a declaration for a method we will call "calculateTheArea:". Put it after the closing elipsis and before the @end. The source will be as follows


./* Calculate */
#import <Cocoa/Cocoa.h>
@interface Calculate : NSObject
{
}
-(float)calculateTheArea:(float)theRadius;
@end

The only line you need to add to what already exists is highlighted above in bold type. This declaration states that the calculateTheArea: method takes an argument of type float, and returns a float value.

Implement AreaOfCircle's Classes.

For the Calculate class, implement the method you just declared in Calculate.h. Method implementations go between @implementation <class name> and @end so this is where you will add the code for Calculate.
68. Select Calculate.m from the Classes group in Project Builder's main window.
69. Insert the highlighted code for calculateTheArea: as shown here:

#import "Calculate.h"
@implementation Calculate
- (float)calculateTheArea:(float)theRadius
{
return (3.141592654*theRadius*theRadius);
}
@end

The calculateTheArea: method of course just returns (PI r squared). Next, update the "empty" implementation of the calculate: method in CircleAreaController.m that Interface Builder generated for you.
70. Select CircleAreaController.m and update code to the following:

#import "CircleAreaController.h"
@implementation CircleAreaController
- (IBAction)calculate:(id)sender
{
float theRadius, area;
theRadius = [radiusField floatValue];
area = [calculateFormula calculateTheArea:theRadius];
[areaField setFloatValue:area];
[radiusField selectText:self];
}
@end

The calculate: method does the following:
* Gets the floating-point value (named theRadius) that the user has typed into the radius field
* Invokes the calculateTheArea:theRadius method and gets the returned value (named area)
* Uses setFloatValue: to write the returned value in the Area of Circle text field (areaField).
* Sends selectText: to the radius field; this selects any text in the field or, if there is no text, inserts the cursor so the user can begin another calculation.

Make sure that CircleAreaController.m imports Calculate.h

71. Add the following line at the top of the CircleAreaController.m source file.


#import "Calculate.h"

Implement the awakeFromNib method.

Before you build the project, add a small bit of code to CircleAreaController.m that will make life a little easier for your users. When the application starts up, you want AreaOfCircle's window to be selected and the cursor to be in the "Radius Of The Circle" field. We can do this only after the nib file is unarchived, which establishes the connection to the text field radiusField. To enable set-up operations like this, awakeFromNib is sent to all objects when unarchiving concludes. Implement this method to take appropriate action.
72. Add the following code to CircleAreaController.m immediately before the @end.

- (void)awakeFromNib
{
[[radiusField window] makeKeyAndOrderFront:self];
[radiusField selectText:self];
}

The makeKeyAndOrderFront: message does as it says: It makes the receiving window the key window (the window that receives input from the keyboard) and puts it before all other windows on the screen. This message also nests another message, [radiusField window]. This message returns the window to which the text field belongs, and the makeKeyAndOrderFront: method is then sent to this returned object.Now after these additions the picture shows what your file should look like.

Sorry No Image
Fig 12 The finished CircleAreaController.m source code

Build and Run the Project.

73. Save source code files and any changes to the project.
74. Click the Build and Go button. If the build is not successful you will have to follow the messages to help you fix up the problem. When the build is successful and the program runs you can enter a radius and get the area.

Extras

Just to demonstrate one of the many extras been built into your application try this. Type a number into the Radius of Circle field and hit Enter. Select the result. Under the AreaOfCircle menu go to Services and choose Speech followed by Start Speaking Text. You will hear the number spoken out. Try other of the Services included in your program for free. Although you have had to follow lots of detailed steps to get to this point, one hopes that with a bit of practice much of it will become easier. It is quite remarkable that so few lines of code are needed to bring to life a fully-featued application with an Aqua user interface.

Further modifications.

You will now be in a position to modify the program to serve other purposes. For example suppose you wanted to calculate the volume of a sphere all you would need to do is to select the Calculate.m file and alter the line

return (3.141592654*theRadius*theRadius);

so that it becomes
return (3.141592654*theRadius*theRadius*theRadius)*4/3;

and then save, build and run the project.
It may worry you that the calculateTheArea method now actually calculates a volume and that the program name and the labels on the user interface are misleading - although the calculation itself will be correct. If you want to tidy all that up you could start a new project from scratch with the new names. I suggest you do as I did when modifying the original ObjCTutorial into the version presented in this article. I wrote out a list of names and titles used in the original project matched up with the new names and titles I needed in the modified project. The table below shows how you might go about modifying the AreaOfCircle project into a VolumeOfSphere project.

Sorry No Image
Fig 13 Use a table of name changes to help you modify the program to calculate volume of a sphere

You could now work through all the steps of this tutorial substituting the new names and formula and create the new application. I'd love to hear how you get on. I can email a copy of the text with modified names. I hope you found this tutorial useful. Good Luck!