
Hello. Welcome to the second tutorial all about starting to code in Objective C and Objective J. In this tutorial I go through an example from the Aaron Hillegass book Cocoa Programming For Mac OS X, 2nd Edition, updating it to work in xCode 3.0, and how the same app is written in Cappuccino 0.7 with nib2cib (using Interface Builder to design the interface).
Fire up xCode 3.0 and choose File->New Project. In the window that pops up choose to make a new Mac OS X Cocoa Application like below:

You will be asked to save it on your Mac. Save it in a sub folder of your User or Documents folder and give the project a name. I’ll call mine RandomAppC. Your new project will open up and xCode will look similar to below.

If you are not familiar with xCode or similar Integrated Development Environment then you may want to read the Xcode Workspace Guide.
We are going to create a new controller object for the random number application. Controllers sit between the view (user interface) and the model (objects representing data). The controller acts as a link allowing access between views and models. In our simple random number application there isn’t going to a model layer as such as we aren’t dealing with any data. If we wrote an address book program we would be dealing with data objects to represent contacts. Read more about the Model View Controller paradigm and it’s place in Mac OS X programming.
We will focus on how to send messages from our application view to the controller. Let’s create the controller.
In xCode choose File->New File… and create a new Objective-C Class like below:

You will see a window similar to below:

Name the file AppController.m and click finish. AppController will eventually contain two methods (seedGenerator and generateNumber) that will be called when a user presses a button in the view. For now we will just leave it blank.
Firstly let’s give our view a reference to AppController. To do this expand the resources folder in the Groups & Files view of xCode and double click on MainMenu.xib to open it in Interface Builder.

Your view of Interface Builder should look something similar to below:

Read more about the Interface Builder Workspace.
We are interested in the window with the title MainMenu.xib and the Library floating panel. The Library panel allows you to browse all the available objects you can make use of in your application view. In the search box at the bottom of the Library type in ‘object’. The lower section will show you some information about the NSObject class. NSObject is the basic building block for all objects in Cocoa programming. Drag an NSObject from the Library like so:

and drop it into the Document Window (titled MainMenu.xib) window:

It’s name will change to Custom Object. No we will make our newly dropped object into our AppController by setting its class.
Your screen will look similar to below:

Now we will drag some user interface objects. In the object library type button and drag and drop two NSButton objects onto our window like so:

Then search the object library for label and drag a NSTextField onto the application window

Let’s resize these objects to fit our window:

With the two buttons and label selected choose the Size section from the Inspector and setup the Autosizing so that each object can grow wider with our window:

Double click on each button and you will be able to edit their text. Name the top one ‘Seed Random Number Generator’ and the lower one ‘Generate Random Number’. As for the label you can remove it’s text – I left it a label in my demo so you can see it hasn’t gone anywhere.
App Controller needs references to our three interface objects so that when a user clicks a button it can run some code and be able to change the text of our label. Communication in this way happens in two directions – from the interface (in this case our buttons) to App Controller and from App Controller to our interface (our label). Actions are used to fire a method in App Controller after an event in the user interface. Outlets are used to allow App Controller to send messages to the interface. Read more about actions and outlets.
So let’s add some outlets and actions to App Controller:

Now we need to link everything together. I never seem to tire of how we do this with drag and drop.
Control dragging a connection from the Seed button to App Controller

Selecting seedGenerator action and making the connection

With everyting laid out and connections between our App Controller and the interface completed, do a quick File->Save.
We are almost done in interface builder, we just need to update the skeleton class of App Controller with our newly created Actions and Outlets. To do this, in Interface Builder:
Choose File->Write Class Files…
You can safely choose the ‘replace’ option when asked whether to merge or replace the existing files.
We’re finished here so you can quit Interface Builder.
Back in xCode we will now write the code that is run when a button is pressed in out interface. Have a look at the contents of AppController.h and AppController.m. You will notice they have been updated with references to the Outlets and Actions we created in Interface Builder.
#import <Cocoa/Cocoa.h>
@interface AppController : NSObject {
IBOutlet id myLabel;
}
- (IBAction)generateNumber:(id)sender;
- (IBAction)seedGenerator:(id)sender;
@end
#import "AppController.h"
@implementation AppController
- (IBAction)generateNumber:(id)sender {
}
- (IBAction)seedGenerator:(id)sender {
}
@end
We need to modify the empty functions in AppController.m so that stuff happens when a user clicks one of our buttons. Make the following changes:
#import "AppController.h"
@implementation AppController
- (IBAction)generateNumber:(id)sender {
//Generate a random number between 1 and 100 inclusive
int generated = (random() % 100) + 1;
//Use outlet to tell label to display the number
[myLabel setIntValue:generated];
}
- (IBAction)seedGenerator:(id)sender {
//Seed the random number generator
srandom(time(NULL));
[myLabel setStringValue:@"Generator Seeded"];
}
@end
I won’t go into great detail as to what we’re doing here as the code is commented. The basics are that it’s a good idea to ‘initialise’ the random number generator before using it (hence the code in seedGenerator method) and we want to generate a new random number everytime the user clicks the Generate Button. The code you can see inside square brackets are messages. You can read more about Objective C syntax.
In xCode you can now click the Build & Go button from the tool bar to run our simple application. Clicking the buttons will alter the label text depeding on the Action performed. So that’s it. A really simple Cocoa App in Objective C. Now, let’s make the same application in Objective J.
We’ll use capp to create a starter application on our desktop. In terminal type the following:
cd ~/Desktop
Followed by:
capp gen -t NibApplication Random
Your terminal will look something like below:

On your desktop you should see the new Objective J application folder called Random. Check out the previous tutorial for an overview of the contents of the generated application folder.
Open MainMenu.xib from the Resources folder to edit it in xCode. You can delete the text field and slider from the window.
Drag the same interface elements onto the window, set the label text and lay out the objects pretty much exactly as we did earlier so that your window looks like below:

You may want to make the label a bit wider than default to accomodate our text and set it to centre align.
Select App Controller from the Document window and in the Identity pane of the inspector:
Your screen should look roughly like below:

So we have updated our MainMenu.xib file. Now it needs to be translated by nib2cib. To do this in Terminal type the following command:
nib2cib ~/Desktop/Random/Resources/MainMenu.xib
The above command assumes your skeleton Cappuccino application is in a folder called Random and sitting on your Desktop. nib2cib will do some churning and your Terminal screen should look similar to below:
Read more about nib2cib. The result of the above command is that nib2cib will have overwritten the existing MainMenu.cib in the Resources folder. You will have to run this command every time you update MainMenu.xib. We can get on with writing some code now by modifying AppController.j. – open up that file in your text editor and modify the code so it looks like below:
/*
* AppController.j
* Random
*
* Created by You on June 23, 2009.
* Copyright 2009, Your Company All rights reserved.
*/
@import <Foundation/CPObject.j>
@implementation AppController : CPObject
{
CPWindow theWindow; //this "outlet" is connected automatically by the Cib
IBOutlet id myTextField; //Out Outlet to the textfield
}
- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
// This is called when the application is done loading.
}
- (void)awakeFromCib
{
// This is called when the cib is done loading.
// You can implement this method on any object instantiated from a Cib.
// It's a useful hook for setting up current UI values, and other things.
// In this case, we want the window from Cib to become our full browser window
//We dont want window to become the full browser window in this case
//[theWindow setFullBridge:YES];
}
- (IBAction)seedGenerator:(id)sender
{
//Set the label text
[myTextField setStringValue:@"Javascript - Can't seed like Objective C"];
//Make sure the new text stays aligned
[myTextField setAlignment:CPCenterTextAlignment];
}
- (IBAction)generateNumber:(id)sender
{
//make a random number and update the text field to show it
var randomnumber=Math.floor(Math.random()*11)
[myTextField setStringValue:randomnumber] ;
[myTextField setAlignment:CPCenterTextAlignment];
}
@end
The main things we have done above are:
IBOutlet id myTextField; This is a reference to the Outlet we created in App Controller in Interface Builder.[theWindow setFullBridge:YES]; We don’t want the window to be full screen in the browser.- (IBAction)seedGenerator:(id)sender This is the code run for the seedGenerator: Action we added to App Controller.- (IBAction)generateNumber:(id)sender This is the code run for the generateNumber: Action we added to App Controller.You should now be able to open up index.html inside your Cappuccino application’s folder and see the app in action.
Hope that helps
As it might be of interest, I will post up some code of the same application written using Cappuccino 0.6 as I was working without nib2cib and using code to layout my interface objects.
Cheers,
Matt
Published on Sunday, June 28th, 2009 at 4:35 pm
I think I’m also in your position, forgetting some ObjC codes after a long hiatus.
Just a quetion, how in the world do I import custom files? i.e. I want to separate some codes into header files. I tried to do:
1. import “headerfile.h”
2. import “../headerfile.h”
which none worked. Any ideas?
Comment by acmecorps — November 8, 2009 @ 4:40 am
[...] which while nearly impossible to use from a traditional HTML/CSS background, makes sense from an Objective-C or Flash/Flex approach: The JS does layout and everything, via absolute positioning, allowing for [...]
Pingback by LSTA Blog » Blog Archive » I launched my first Google App Engine hosted app! :-) — November 10, 2009 @ 8:17 am