Hello, Objective C
Sun Jul 11th 2004, 10:23pm
I wanted to learn about Cocoa programming, so I picked up Cocoa Programming for Mac OS X (second edition), by Aaron Hillegass. I think I read about it on Slashdot a long time ago, and had it on my wish list for a while. The book is pretty good so far, though I've really only just gotten started, so I thought I'd write something up on my initial impressions of Objective C.

Among other crazy things, Cocoa programming is mostly done in Objective C, which is a lightweight extension of C that makes it a loosely typed, object-oriented language. That, combined with a powerful set of NeXTStep support libraries, makes it almost feel like a higher-level scripting language. Hillegass devotes about 40 pages to a crash course in ObjC, aimed at intermediate or better programmers who've done the whole OO thing already in some other language (e.g. Java, C++). I have a few nits about it, but granted the book isn't about ObjC, it's about Cocoa, and eventually most of my burning questions during the chapter were answered, if not as early as they could have been.

It seems to me if you've done Java, then the concepts of classes, interfaces, instance variables, and static and instance methods translate over directly. That and if you've done C in the past, then you're pretty much set as far as pointers, addresses, etc. go. The only really screwy thing with it is its approach to memory management: the programmer manages reference counts, you call retain and release methods on objects, and to top it off some objects are autoreleased for you. Seems very powerful, if you can get your head around it. [Update May 1st, 2008: ObjC has garbage collection now]. Oh... and one more thing, the syntactical screwiness. The whole language looks really nutty; the author mentions that it was originally implemented as a C preprocessor, which totally makes sense when you look at it--funny '@', '-', and '[]' symbols everywhere, and other things which are (were?) clearly macros. This isn't C anymore.

So I thought I'd share my HelloWorld program. How exciting. Pretty much the typical "Hello, world", if not quite as ultra trivial, with a simple HelloWorld class that I think demonstrates some of the syntactical and memory management nuttiness involved here.

First the class declaration, HelloWorld.h:
#import <Foundation/Foundation.h>

@interface HelloWorld : NSObject {
    // no instance variables
}

// methods
- (void)sayHello;

@end
Read that @interface line like "Class HelloWorld inherits from NSObject". Instance variables go inside the curly brackets, methods underneath. The bizarre leading '-' indicates sayHello() is an instance, not a static ('+'), method. Then the implementation, HelloWorld.m:
#import "HelloWorld.h"

@implementation HelloWorld

- (void)sayHello
{
    NSLog(@"Hello, world, at %@", [NSCalendarDate calendarDate]);
}

@end
We're using stuff from the NeXTStep libraries here, NSLog is like a printf() (printf() would have worked fine, but Hillegass is teaching us the NS stuff). %@ is cool, it calls the object's description() method and substitutes the results (i.e. toString()). More on the square bracket stuff next. Then the main program to drive it, main.m:
#import <Foundation/Foundation.h>
#import "HelloWorld.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // my stuff
    HelloWorld *hw = [[HelloWorld alloc] init];
    [hw autorelease];
	
    [hw sayHello];
	    
    [pool release];
    return 0;
}
Java guys, read the "[HelloWorld alloc]" syntax as HelloWorld.alloc(), or actually as new HelloWorld(). Note alloc() is a static method in this case. [Added May 1st, 2008: As Aaron (Hillegass?) points out in the comments below, it's important to call init() on the object in addition to alloc() so proper initialization happens, instead of simply allocating the memory for it. It's surprising my program didn't crash.] [hw sayHello] calls the sayHello() method.

So here's my take on the memory management bit. ObjC has no garbage collection, so we're back to the days of fooling around with this stuff (argh, haven't we learned anything? Anyways...) Objects maintain a reference count which the developer can manipulate by calling the retain() or release() methods. Objects destroy themselves when their reference count hits zero. This way shared objects exist for as long as they need to exist, and go away when no one wants them anymore. Slick. When you alloc() an object, it's reference count is set to 1. At the end of main() I could have called [hw release] to destroy it, or in this case, I chose to take advantage of the NSAutoreleasePool convention, which is this collection bin for holding objects to be released later, at a time of the programmer's choosing--specifically, you can see at the end of the main() method ([pool release]). By calling [hw autorelease], the hw object told whatever pool object in scope to reference it (incrementing its ref count), then decremented its reference count (well, I'm sure internally they optimize this to not do anything, since it's a wash, but that's the idea). This way my memory management (creation/deletion) is handled all in one spot--I've created it, and I've effectively freed it, but should someone else want it before I'm done with this method they can have it. This "delayed destruction" approach seems pretty clever, and has a more few more practical applications which are not really demonstrated by my simple Hello World program.

(Update Mar 3 and 20th, 2009): To compile and run all this, use a Terminal and gcc (thanks Mina and Ade!):
$ gcc main.m HelloWorld.m -framework Foundation -o hello 
$ ./hello
2009-03-20 11:39:06.444 hello[78751:10b] Hello, world, at 2009-03-20 11:39:06 -0700

At the top of the article I said "Cocoa programming is mostly done in Objective C" deliberately to bring up that Apple actually provides all the Cocoa/NeXTStep APIs in Java, so if you wanted, you could write (very non-portable) Java code to create Cocoa apps. It seems to me it must be a lot of work to keep both languages up to date with any API changes. (Update Mar 3 2009: and indeed, this "Java bridge" API is deprecated as of Mac OS 10.4, so never mind). However, while this may seem exciting to the ObjC-adverse, Hillegass points out that "almost no one is developing Cocoa apps in Java", mainly citing performance, but also pointing out potential bugginess and how Java just isn't the right tool for the job. Too bad! (Update Mar 3, 2009: five years later and my how my perspectives have changed--I'd pick ObjC in a heartbeat over Java).



Visitor comments
On Wed Oct 26th 2005, 7:46am, Visitor posted:
Hey, thanks. That was the best short objective-c introduction I've found so far :-)


On Sun Mar 4th 2007, 1:55pm, Visitor posted:
Holy shit, C++ SEEMS pretty more easy so far.


On Tue Mar 4th 2008, 11:17am, KeNJlRo posted:
I've just started learning Objective C.

Thank for explanation and your code.



On Fri Mar 7th 2008, 12:09pm, kronos posted:
thanks for your explanation, it cleared up a lot of things for me.


On Fri Mar 7th 2008, 1:06pm, Steve Kehlet posted:
You're welcome KeNJlRo and kronos! I wonder if this page got linked somewhere.

I would add that I heard Objective-C 2.0 (i.e. Leopard+) has garbage collection. Hooray. http://developer.apple.com/leopard/overview/objectivec2.html


On Thu Mar 20th 2008, 9:36pm, Visitor posted:
Great article! ...but OMG! Objective-C... it's like C and C++ had a retarded child that was raised by make.


On Sat Apr 19th 2008, 8:25pm, Visitor posted:
That is insanely complicated way to display Hello World. It has effectively scared me away from Obj C.


On Mon Apr 21st 2008, 11:40am, Steve Kehlet posted:
Yes, it's "Hello World", but also demonstrating classes, instance methods, memory management (no longer necessary with ObjC 2.x, which now has garbage collection), and using a few NeXTStep libraries. An equivalent example in Java would probably be just as long. But yes, ObjC's syntax is a bit scary, and I did deliberately make this example more complicated than it needed to be as a small jab against what seemed at the time (note this article is from almost 4 years ago) to be a rather anachronistic and downright ugly language. But I'd say with garbage collection now I could probably overlook all that, and, as tempting as it would be to look to RubyCocoa or equivalent Python/Cocoa bindings, some people (e.g. http://theocacao.com/document.page/428/) have a point that Ruby/Python/etc don't really have much over ObjC in terms of features and--more importantly--clarity.


On Wed Apr 30th 2008, 11:48pm, Dan Morphis posted:
Steve, thank you for providing this article. For me, it has help to clear up some of the basic things for me in regards to the objective-c language.


On Thu May 1st 2008, 4:35pm, Visitor posted:
Hi Steve.

Nice article.

This line:
HelloWorld *hw = [HelloWorld alloc];

should be:

HelloWorld *hw = [[HelloWorld alloc] init];

If you do not call init, you have broken the chain of initialization (the superclasses do not have a chance to perform initialization), and it is likely to cause problems at runtime. By just calling alloc, you have set aside a block of memory, and anything may be in it.


Aaron


On Thu May 1st 2008, 5:26pm, Steve Kehlet posted:
Aaron, thanks for the fix! I've updated the code above.


On Tue Jun 3rd 2008, 1:54pm, Guilherme Chapiewski posted:
Pretty Cool :) Just to make it more complete, I think you should add something about compiling and/or running this code using XCode.

gc


On Sat Jul 19th 2008, 2:38am, Visitor posted:
Excelent article


On Fri Oct 3rd 2008, 11:30am, Douggs posted:
Excelet post!!

Can post here some example how do a GUI with object-c ?

Thanks a lot,




On Fri Jan 16th 2009, 5:10am, BillyJo posted:
What should you use to compile this? I understood MacOS X's gcc should work with Objective C - but:

$ gcc main.m
Undefined symbols:
".objc_class_name_NSAutoreleasePool", referenced from:
literal-pointer@__OBJC@__cls_refs@NSAutoreleasePool in ccfLvrzh.o
".objc_class_name_HelloWorld", referenced from:
literal-pointer@__OBJC@__cls_refs@HelloWorld in ccfLvrzh.o
"_objc_msgSend", referenced from:
_main in ccfLvrzh.o
_main in ccfLvrzh.o
_main in ccfLvrzh.o
_main in ccfLvrzh.o
_main in ccfLvrzh.o
_main in ccfLvrzh.o
_main in ccfLvrzh.o
ld: symbol(s) not found
collect2: ld returned 1 exit status




On Fri Jan 16th 2009, 2:18pm, Steve Kehlet posted:
It's been so long I can't remember... I don't remember even if I used Xcode or the command line. I found this site which might help:

http://blog.lyxite.com/2008/01/compile-objective-c-programs-using-gcc.html

Looks like you have to do:

gcc -o hello hello.m \
-L /System/Library/Frameworks/Foundation.framework/Foundation



On Fri Feb 20th 2009, 2:06pm, Mina posted:
The actual command to compile the above 3 files in the article is:

gcc main.m HelloWorld.m -L /System/Library/Frameworks/Foundation.framework/Foundation -fobjc-gc-only -o main


On Tue Mar 3rd 2009, 10:10am, Steve Kehlet posted:
Thanks Mina!


On Thu Mar 19th 2009, 9:05pm, Ade Barkah posted:
It's better to use -framework:

$ gcc main.m HelloWorld.m -framework Foundation -o hello
$ ./hello


On Fri Mar 20th 2009, 2:06pm, Steve Kehlet posted:
Even better, thanks Ade!


On Wed Sep 21st 2011, 4:47pm, Visitor posted:
"It's surprising my program didn't crash."

Your program didn't crash because it has no state to initialize.