Programming for the Macintosh OS X: Cocoa Code Examples / Tips & Tricks

What do I need? First: Macintosh G3, G4 or higher. Second: OS X 10.2 or higher. Third: OS X Developer CD.

Already experience in Objective-C ? (If not see my Objective-C vs. Delphi comparism sheet that is mainly useful if you have a basic knowledge of Windows Delphi). Ansi-C is a real subset of Objective-C so you can easily port your old classic C applications to the Mac. Cocoa is a collection of the frameworks totally written in Objective-C. On the other hand Carbon is a successor of the classic Macintosh API.

Let's begin dealing with objects...


Creating Object Instances

Creating an object and calling init MyObject *myObject = [[MyObject alloc]init];
Deallocating object [myObject dealloc];
Increasing reference counter of object [myObject retain];
Decreasing reference counter of object - object will receive a dealloc message if counter equals 0. [myObject release];
Creating an object and add it to the autorelease pool that will send all added objects a dealloc message on application termination. MyObject *myObject = [[[MyObject alloc]init]autorelease];

 

String Handling

Creating a string with constant NSString *aString = @"Hello";
Creating a blank string NSString *aBlankString = [[NSString alloc]init];
Creating a string with content of a C-String NSString *aString = [[NSString alloc]initWithCString: aCString];
Creating a string with content of another

NSString *anotherString = [[NSString alloc]initWithString: aString];
or
NSString *anotherString = [ExistingString copy];

Creating a string with format

NSString *aFormattedString =
[NSString stringWithFormat:@"number: %i , text: %@", i, anotherString];

Comparing two strings BOOL result = [string1 isEqualToString: string2];
Getting a C-String aCString *char; aCString = [aString cString];

 

Simple Output

Output a message to console

NSLog(@"YourTextMessage");
will result in:
2003-04-02 20:59:08.854 MyApplication[2172] YourTextMessage
Output message with format NSLog(@"text: %@, number: %i", aText, i);

 

Arrays

Creating a mutable array NSMutableArray *mArray = [[NSMutableArray alloc]init];
Adding elements [mArray addObject:@"Test"];
Retrieving elements NSString *s = [mArray objectAtIndex:0]
Removing all objects from array (and sending them a dealloc message) [mArray removeAllObjects];

 

Global Defined Class Instances

NSApplication instance NSApp

 

Images, Graphics, etc.

Creating an image with content of an image (.JPG/.TIFF/.GIF etc.)

[ NSImage *img = [[[NSImage alloc]
initWithContentsOfFile: aPath]autorelease];

Retrieving system image for a registered file type NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSImage *img = [ws iconForFile: aPath];
Rescaling an image

[img setScalesWhenResized: true];
[img setSize: NSMakeSize( 100, 120) ];

   

 

GUI

Accessing a text field

In Cocoa GUI elements are accessed by so called outlets. For every element you wish to access you define one outlet in the interface of your controller class:

@interface MyController : NSObject {

IBOutlet NSTextField *oMyTextField;

}

Implementation:

[oMyTextField setStringValue:@"hello"];

[oMyFloatTextField setFloatValue:4.5];
[oMyIntegerTextField setIntValue:100];












Don't forget to assign your outlet to the GUI element you wish to access:

1. Drag your controller header file (.h) into Interface Builder to inform it about your new outlet:

2. Connect the outlet from the controller to your GUI element:


Choose your outlet (oMyTextField) in the Info Dialog and select connect.

Displaying an alert box NSRunAlertPanel( @"Hi folks!", @"How are you?", @"Fine", nil, nil);
Opening a panel for choosing a directory NSOpenPanel *op = [NSOpenPanel openPanel];
int iResult;

[op setCanChooseDirectories : YES ];
[op setCanChooseFiles : NO ];

iResult = [ op runModalForDirectory : NSHomeDirectory () file: nil types: nil];

if (iResult == NSOKButton) [oDestinationFolder setStringValue: [op filename] ];

Grouping image buttons in a matrix (e.g. for a thumbnail browser)

Create a Square Button (NSButton, type: square button) and multiple it by enlarging its size while selecting ALT-key (the NSMatrix appears in the info title).

Choose "Layout->Make subviews of Scroll View" from Menu to put your ButtonCells into a scroll view.

Define an outlet for your matrix and set the title and image of a cell of your matrix (assuming that oMatrix is your outlet):

NSCell *cell = [oMatrix cellAtRow:y column:x];
[NSImage *img=[[[NSImage alloc]
initWithContentsOfFile:"pic.JPG"]autorelease];
[cell setImage: img];
[cell setTitle: @"My Picture Title"];
[oMatrix display];

[oMatrix numberOfColumns] and [oMatrix numberOfRows] will return the number of rows and columns.

[oMatrix addRow] and [oMatrix sizeToCells] will add a row and size the cells to fit.

Application example for NSMatrix:

One NSButton (Square Button)



can be multiplied to a farm of NSButtonCells (NSMatrix):



Don't forget to connect your controller class with NSMatrix:

 

Time, Date and Timers

Wait a specified time intervall

[ NSTimeInterval t;
t = [NSDate timeIntervalSinceReferenceDate];
while ([NSDate timeIntervalSinceReferenceDate] < t + 0.1);

 

Events (Delegates and Actions)

Action method that is called when the user clicks an control element (e.g. a button) on a window

Insert in interface section of your controller class:

@interface MyController: NSObject
{
...
}
- (IBAction)cancelClick:(id)sender;
@end

Implementation:

- (IBAction)cancelClick:(id)sender{
NSLog(@"Cancel was clicked!");
}

Don't forget to connect the button with your controller class:



Since the button will send us a message we connect the button with the controller and not vice versa (as for accessing a text field from the controller class).

Delegate method that is called when the user clicks the close button on a window

Insert in interface section of your controller class:

- (BOOL)windowShouldClose:(NSWindow *)sender;

Implementation:

- (BOOL)windowShouldClose:(NSWindow *)sender {

if (stillWorking) return NO;
else return YES;

}

 
Don't forget to connect the delegate outlet of your window with your controller!


Files, Tools and Other

Open external file or folder

NSWorkspace *ws = [NSWorkspace sharedWorkspace];
[ws openFile: [optionsWindow destination]];

Get path of a resource file in the bundle NSString *imgCDPath = [[NSBundle mainBundle] pathForResource:@"CD" ofType:@"tiff"];
Checking the User's Mac OS X Version if (Gestalt(gestaltSystemVersion, &macVer) == noErr)
NSLog(@"Mac OS version: %x.%x.%x (hex: %xh)", macVer >> 8, (macVer >> 4) & 0xF, macVer & 0xF, macVer);
Getting available real memory NSLog(@"Real Memory available: %d KB", NSRealMemoryAvailable()/1024);


Creating and assigning Application Icon

1. First design your icon (.TIFF, 128 x 128 pixels) - keep sure your graphics application can handle a mask/selection of your image correctly which is needed for transparency.
2. Create a .icns file for your icon with IconComposer (you will find it in /Developer/Applications folder) and drag this file into Application Builder
3. In menu "Project-> Edit Active Build Style-> Simple View-> Info.plist" enter your icon file name
4. Compile and link your application. That's it!


Deployment and Shipping

How to ship your applications?

If you have created a final version (by setting target as "deployment" in the application builder), you surely want to ship this software bundle. The MAC OS X does not support copying bundles. If you want to ship them, you must create an image and copy all the file needed for shipping on it.

1.) get root: "sudo -s"
2.) create an image file: "hdiutil create 'TESTAPP.DMG' -kilobytes 400 -layout NONE
3.) Make image known to MAC OS (for formatting we need an unmounted media): "hdid TESTAPP.DMG -nomount"
4.) Format this virtual image: "newfs_msdos -v NO_NAME -b 512 /dev/diskxyz"
5.) Eject the image: "hdiutil eject /dev/diskxyz"
6.) Mount image: "hdid TESTAPP.DMG"

The image drive will appear with the name of your volume name on the desktop.

7.) Now you are ready to copy the bundle (and other files belongig to your application) to the image. The image is like a setup-file ready for distributing to the customer.


Any questions / comments to this page? Please don't hesitate to contact me: greymfm[at]hotmail.com (Replace [at] by @)