The author of this FAQ is Graham Lee and all comments and corrections should be addressed to him. It was written with the invaluable help of the denizens of comp.lang.objective-c, especially Michael Ash for writing the sections on categories, protocols and thread synchronization, and providing much input on the section on selectors and implementation pointers.
Yes, that's correct. The official FAQ, maintained by David Stes, can be found at rtfm.mit.edu. However that FAQ is out of date, and contains a number of errors or omissions in the sections on GNU and Apple Objective-C. I provided updates to that FAQ which have not been implemented (yet) by David. In this FAQ I aim to provide an expanded, corrected and updated replacement to that original. Hopefully this will become a more complete and accurate FAQ list for comp.lang.objective-c.
The version you are reading was updated on 22/07/2006. The current version may be found at nextstep.sdf-eu.org, but beware that the URL may soon change. Any change will be posted to the newsgroup.
Objective-C was invented in the early 1980s by Dr. Brad Cox. The language was developed as an Object-Oriented layer on top of the popular C programming language (in this FAQ and in much other documentation on Objective-C, knowledge of C or a related language is assumed). Cox's original implementation was a preprocessor which generated C code, and was marketed by Stepstone.
Objective-C is a true superset of C, so the language may vary depending on what version of the C language is supported by the compiler. The additions to C are few: a handful of new keywords, three extra types (of which only one,
id
, is frequently used) and the message-sending syntax.
There is no standards document describing the Objective-C language as there is for C, C++ and other languages. The canonical descriptions of the language are therefore its implementations; see below.
By far the most popular and actively-developed variant of Objective-C is that maintained by Apple, based on the GNU C Compiler. The 'vanilla' GNU C Compiler from the Free Software Foundation also supports the language; its implementation is very similar to that provided by Apple although newer features take some time to trickle down, and the two runtimes are not compatible with each other. David Stes' POC implementation is incompatible with the above two, and doesn't contain many of the features of Apple's Objective-C implementation. On the other hand, it does provide blocks (a Smalltalk feature, also found in Ruby) and class variables.
The organisation of Objective-C source is typically similar to that of C or C++ source code, with declarations and object interfaces going into header files named with a .h extension, and definitions and object implementations going in files named with a .m (short for methods) extension.
The ubiquitous gcc is one Objective-C compiler (though there are two flavours, discussed below). David Stes' Portable Objective-C Compiler (POC) is an Objective-C preprocessor which uses the gcc to compile its output.
Historically, NeXT Computer (latterly NeXT Software) and Stepstone produced Objective-C compilers, however both companies no longer exist. NeXT's acquisition of Stepstone's Objective-C rights and Apple's subsequent acquisition of NeXT mean that Apple Computer now control their respective interests in Objective-C. Metrowerks also used to have an Objective-C compiler in their CodeWarrior development environment, but this is now defunct too.
Objective-C files can be edited in standard text editors, and editors such as emacs have syntax highlighting modes for the language. Integrated Development Environments with support for the Objective-C language include Apple's Xcode and GNUstep's ProjectCenter.
With just an Objective-C compiler it's possible to go ahead and code, but you'd have to reinvent a lot of wheels before getting to any interesting programming. A class library provides a pre-made set of objects and classes, usually offering functionality such as containers, data handling and user interfaces.
Many of the class libraries available for Objective-C are derived from OpenStep, by NeXT Computer and Sun Microsystems. These include Apple's Mac OS X-specific Cocoa, and the cross-platform GNUstep. Both of these provide class libraries with a Foundation (containers, strings, networking/IPC etc) and AppKit (user interface components), as well as their own specific classes. Implementations of just the Foundation part include OpenDarwin's libFoundation.
Swarm is an Objective-C framework for agent-based modeling.
The POC comes with its own ObjPak library, offering strings and collections.
#import
thing?
#import
is a pre-processor directive similar to C's
#include
, except that it will not include the same file twice. This makes
#ifdef
guarding inside header files unnecessary. Some versions of gcc emit warnings when
#import
is used; you can turn those off with
-Wno-import
.
The same comment styles that C supports may be used. They are comments which start with
//
and run to the end of a line:
// this is a BCPL-style comment
and comments which start with
/*
and end with
*/
:
/* this is a C comment * it spans multiple lines * note that comments of this type cannot be nested! */
The Objective-C keyword
id
is a type corresponding to a reference to any object. More rigourous type-checking can be enforced by using a pointer to a specific class, such as
MyClass *
. Any object whose class is
MyClass
or one of its subclasses can then be used; an object of any other class used here would cause an error.
self
and
super
mean?
self
is a special variable available in method implementations to refer to the current object (i.e. the one which received the message to invoke this method).
super
can be used to have an object invoke its superclass's implementation of a method. One common use of both of these is in initialisation:
-(id)init { if((self=[super init])) { // invoke superclass -init someIvar=[[MyClass alloc] init]; } return self; //i.e. return this object }
The object representing the class of another object can be returned by sending the
-class
message, as in:
MyClass *someObject=[[MyClass alloc] init]; id aClass=[someObject class];
Class objects behave as instances of the root class (i.e.
[aClass class]
will return the root class). The object
aClass
is now the class object
MyClass
, and responds to class messages in the same way that sending messages to
MyClass
behaves; e.g.
[[aClass alloc] init]
will create a new instance of
MyClass
.
nil
?
nil
is the null object, used to refer to uninitialised or cleared objects (and
Nil
is the null class object). Unlike in other languages, in Objective-C it is legal to send messages to
nil
; the return value is
nil
for type
id
, 0 for simple C types such as
int
, and undefined for compound types such as
struct
. Both
nil
and
Nil
are defined as
(id)0
.
@defs
?
The
@defs()
keyword provides a list of C declarations of the in-memory layout of an object of a given class. It can therefore be used in generating a C API to Objective-C objects:
struct MyClass_t { @defs(MyClass) };
In short, you don't. You could have the parameters of a message include context information (such as
-(id)doSomething:(id)sender
) but then you're still dependent on the sender providing accurate context.
No - you should normally just have to recompile that class and all subclasses. Any C source which uses
@defs()
(or anywhere else you directly access instance variables) should be recompiled, as the in-memory layout of the class will have changed. Any parts of your code which just access the instance variables through accessor methods or KVC/KVO (see "What are key-value coding and key-value observing?" below) will not need recompiling.
A category is a way to add methods to a class which already exists. It appears in code as a second set of
@interface
and
@implementation
. declarations, which contain methods that get added to the class when the category is loaded at runtime. Categories are only available in compilers which implement the gcc variant of Objective-C.
The interface declaration for a category looks like:
@interface ClassName (CategoryName) -method; @end
The category name has no influence at runtime, but it must be unique with respect to other categories on the same class, and it will appear in stack traces.
The implementation declaration is similar:
@implementation ClassName (CategoryName) -method {...} @end
Categories can be used to split a single class's implementation into multiple files by splitting the implementation into categories and putting each one into a different file. Categories can also be used to add methods to a class whose source code you don't control, for example adding a
-md5Sum
method to a data container that's part of your class library.
A protocol is basically an interface without an implementation. It's a set of messages that are bundled up together in a convenient package. You can then use the protocol to declare that a class implements the entire set of messages, and check objects to see if they conform to the protocol. You can also use protocols in a variable type declaration to show that you need a certain set of methods but don't care about the actual class of the object. Protocols are only available in compilers which implement the gcc variant of Objective-C.
You declare a protocol like this:
@protocol ProtocolName -method; @end
It's possible for a protocol to inherit from another protocol, which works much like classes where the "parent" protocol's methods get added to the "child". In that case, the first line of the declaration would look like:
@protocol ProtocolName <ParentProtocol>
Write the class's interface declaration like this:
@interface ClassName <ProtocolName>
To declare conformance to multiple protocols, just separate the protocol names with commas.
For Object, write:
[obj conformsTo:@protocol(ProtocolName)]
For NSObject, write:
[obj conformsToProtocol:@protocol(ProtocolName)]
To declare a variable which conforms to a protocol but otherwise has no restrictions on type, write:
id <ProtocolName> obj;
To declare a variable which is an instance of a certain class and which also conforms to a protocol, write:
ClassName <ProtocolName> *obj;
Note that this construct is rare.
An informal protocol isn't actually a protocol at all, but rather a category interface declaration with no corresponding implementation. Informal protocols are frequently used in Cocoa to declare a set of methods to the compiler in a situation where there is no point in having a formal protocol, for example where many methods are optional.
SEL
? How do I get one?
SEL
is a C type referring to a method selector (i.e. they uniquely identify particular messages). They can be obtained through use of the
@selector()
keyword:
SEL aSelector=@selector(doSomethingWithStuff:);
or through use of a runtime function. The appropriate function is
sel_getUid()
on Apple gcc,
sel_get_any_uid
on GNU gcc and
selUid()
on POC.
perform:
and
performSelector:
do?
They send the message corresponding to the specified selector to an object. That is,
[obj performSelector:@selector(message)]
is the same as writing
[obj message]
. The difference is that
perform:
and
performSelector:
can be passed a variable as its argument, whereas a plain
[obj message]
must always send the same message.
IMP
? How do I get one?
IMP
is a C type referring to the implementation of a method, also known as an implementation pointer. It's a pointer to a function returning
id
, and with
self
and a method selector as the first arguments:
id (*IMP)(id, SEL, ...);
With NSObject, you can obtain the
IMP
for a given method by doing:
IMP imp=[obj methodForSelector:@selector(message)];
For Object, do:
IMP imp=[obj methodFor:@selector(message)];
IMP
?
Dereference it, as with a C function pointer:
id anObject, theResult; IMP someImp; SEL aSelector; // ... theResult=someImp(anObject,aSelector);
IMP
for methods returning non-
id
types?
IMP
s are pointers to methods which return
id
. Just using one with a
SEL
that doesn't return
id
is going to cause trouble, so you should provide a new prototype and cast to that instead:
int (*foo)(id,SEL); int result; foo=(int(*)(id,SEL))[anArray methodForSelector:@selector(count)]; result=foo(anArray,@selector(count));
SEL
for methods returning non-
id
types?
You can do this by either using your runtime's message sending functions directly, or by obtaining the
IMP
for the method and casting it as discussed in the previous question.
In the Apple/NeXT runtime, the message sending function is
objc_msgSend()
, but beware the many variants which need to be used depending on the return type of the method. See
/usr/include/objc/objc-runtime.h
for more details.
In the GNU runtime, you could use
objc_msg_sendv()
, and someone who knows how should write about that...
In POC, you should Find someone who knows what to write about...
An exception is an event which occurs in running a program which causes the normal flow of the program to be interrupted. Programmers coming from other object-oriented languages such as Java will be familiar with exceptions. In Objective-C programming, it's typical to find exceptions used solely for programmer error (such as testing assertions), with user-visible errors being handled as part of the normal program flow.
Exceptions are available in the gcc dialect of Objective-C (currently only with the NeXT runtime; see "Why do people refer to GNU gcc and Apple/NeXT gcc?" below), and must be enabled with gcc's
-fobjc-exceptions
. Code which could throw an exception is contained in a
@try
block. This is then followed by one or more
@catch
blocks to process any exception thrown. A subsequent
@finally
block contains code which should be run whether or not an exception occurred. An exception can be any object, and is thrown with the
@throw
keyword. An example:
@try { //code which may cause an exception to be thrown ... } @catch(MyExceptionClass *ex) { // handle a custom exception ... } @catch(id *ex) { // generic exception handler ... } @finally { // this will happen whether or not an exception occurred. ... }
In the above case, two
@catch
blocks exist; one for a specific type of exception and one for catching generic exceptions. The most specific handler should always come first. Be warned that exceptions are fragile to changes in the call stack such as
goto
or
return
.
Yes; invoke
@throw()
with no arguments in the
@catch
block, in order to re-throw the caught exception.
NS_DURING
and
NS_HANDLER
. What's that?
Before gcc had an exceptions syntax for Objective-C, Cocoa provided its own exception-handling mechanism, based on macro wrappers for the standard C
longjmp()
and
setjmp()
functions. The implementation of Objective-C's language exceptions (i.e.
@try
and friends) is currently binary compatible with
NS_DURING
and friends.
@synchronized
?
@synchronized
is a directive that supports simple locks for multithreaded programming. It is only available in the gcc variant of Objective-C, and is enabled in the NeXT runtime by the gcc
-fobjc-exceptions
flag (see Exceptions above). It allows an implicit associated lock with any object, without having to explicitly create or manage locks. If you are familiar with Java, it is basically identical to Java's synchronized construct.
@synchronized
?
The syntax is as follows:
@synchronized(object) { ... }
This will lock on "object", meaning that any other threads which hit a
@synchronized
directive with the same object will not proceed until this thread has exited its
@synchronized
block. It is basically the same as this code:
[[object getLock] lock]; ... [[object getLock] unlock];
With the exception that the object itself is not responsible for having such methods or managing an explicit lock object.
Not having to explicitly create or destroy locks can make code easier to write and easier to read.
@synchronized
is also aware of return statements and exceptions, so you can be sure that the lock is always released even if the flow of control exits from the middle of the block.
@synchronized
is slower than explicit locks, because the overhead of looking up the implicit lock is significant. It also always uses a recursive lock, which is slower than a non-recursive lock. It is also less flexible, not supporting condition variables or other advanced threading concepts.
The version of gcc used by Apple (and NeXT before them) provides a different Objective-C implementation (specifically, the runtime is different) from that distributed by the Free Software Foundation. Darwin and Mac OS X ship with the Apple gcc, upon which Cocoa depends. Typically other operating systems will have the GNU Objective-C variant, and it is this which GNUstep requires. However the source to both versions of the compiler are available so you could build whichever you want for your platform. Because Apple uses its own version of gcc, the features available in the two variants may differ at any time. Be sure to check the documentation for your version of gcc, to make sure that a feature you expect does indeed exist.
Without any reliance on class libraries, an invocation such as:
gcc -c myfile.m -lobjc
will work. Check the documentation for your class library otherwise: for instance with Cocoa you might use:
gcc -framework Cocoa -c myfile.m
gcc supports the mixing of Objective-C and C++ in files named with a .mm extension, called Objective-C++. This allows, for example, Objective-C objects to be instance variables of C++ objects and vice versa. It does not allow Objective-C classes to inherit from C++ classes or vice versa. The Objective-C and C++ exception mechanisms are completely different too, so you cannot use a C++
catch
to catch an
@throw
n exception.
If you use an Objective-C string literal such as
@"Hello world!"
, then the class of the resulting object will usually be
NXConstantString
. This can be modified at compile-time though, using gcc's
-fconstant-string-class
argument. In Cocoa, the class of a string literal is
NSConstantString
.
objc -c myfile.m
Yes; as POC is an Objective-C to C preprocessor you can freely mix Objective-C and C++.
#import <Foundation/NSObject.h>
For completeness, note that NSProxy is also a root class.
If an object receives a message it doesn't respond to, the runtime will also send it a
-forwardInvocation:
message before an error occurs. This means that you can override the method
-(void)forwardInvocation:(NSInvocation *)inv
in your class to have unrecognised messages forwarded to other objects; see Forwarding at developer.apple.com. You also need to override
-(NSMethodSignature *)methodSignatureForSelector:(SEL)selector
otherwise
forwardInvocation:
does not get called.
Here's a simple example of forwarding, which is used to internalise a loop performed on a collection class. That is, we're going to give collections a way to send a message to each of their contents. Firstly, a trampoline class
CollectionTrampline
is required which, given a collection, forwards any message it receives to the contents of that collection. This is the interface for the class:
@interface CollectionTrampoline : NSProxy { id theCollection; } - (id)initOnCollection:(id)aCollection; @end
Here are the instantiation and deallocation methods:
- (id)initOnCollection:(id)aCollection { theCollection=[aCollection retain]; return self; } - (void)dealloc { [theCollection release]; [super dealloc]; }
As described above, we need to override
methodSignatureForSelector:
to have forwarding work. Return a signature corresponding to a
-(void)
method, as we don't provide any way to access the return values from the forwarded invocations:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { return [NSObject instanceMethodSignatureForSelector:@selector(release)]; }
Now our implementation of
forwardInvocation:
. Here, an
NSEnumerator
is used to iterate through the objects, and the method is invoked on each:
- (void)forwardInvocation:(NSInvocation *)anInv { id i; NSEnumerator *en=[theCollection objectEnumerator]; while(i=[en nextObject]) { [anInv invokeWithTarget:i]; } }
Finally, the collection classes must have a way to return a trampoline object. Here's a category on
NSArray
to do that:
@interface NSArray (Trampolines) - (id)do; @end @implementation NSArray (Trampolines) - (id)do { return [[[CollectionTrampoline alloc] initOnCollection:self] autorelease]; } @end
Now this trampoline can be used to send a message to every object in a collection:
[[anArray do] doSomething];
While there is currently no automatic garbage collection for gcc's Objective-C, reference counting takes some of the workload away from manual memory management. Objects descended from NSObject have an intrinsic reference count which starts at 1. If you depend on an object staying around, send it a
-retain
message. When you are done, send it
-release
. An object will not be deallocated until its reference count reaches 0.
A good article on reference counting is Hold Me, Use Me, Free Me.
In Cocoa, Key-Value Coding (KVC) and Key-Value Observing (KVO) provide an indirect route to inspecting and modifying properties of an object. The principle use of KVC and KVO is in Cocoa Bindings, an efficient approach to synchronising an application's user interface with its data model.
If the object
myObject
provides accessor methods such as
-someVariable
and
-setSomeVariable
, or an instance variable called
someVariable
or
_someVariable
, where
someVariable
is of type
id
, then the value of
someVariable
can be accessed (even if it's a derived property) through code such as:
[myObject valueForKeyPath:@"someVariable"]; [myObject setValue:@"Hello" forKeyPath:@"someVariable"];
Another object, such as
myOtherObject
, could be notified when the value of
someVariable
changes through KVO:
[myObject addObserver:myOtherObject forKeyPath:@"someVariable" options:NSKeyValueObservingOptionNew context:NULL];
now when
someVariable
is modified,
myOtherObject
will receive a
-observerValueForKeyPath:ofObject:change:context:
message.
See the KVO Programming Guide and the KVC programming guide.
#import <Object.h>
When an object receives a message it doesn't respond to, the runtime will also send it a
-doesNotUnderstand:
message before an error occurs. This means you can implement
-doesNotUnderstand:(id)aMessage
to provide message forwarding. To send a message on to a proxy object, provide that object as the argument to aMessage's
-sentTo:
method.
Class variables should be declared in curly braces after the instance variables:
@interface MyClass:Object { float instanceVar; } : { int classVar; } @end
As well as the references throughout this FAQ, there's The Objective-C Programming Language and:
Duncan, A.M., Objective-C Pocket Reference, O'Reilly Media (ISBN: 0-596-00423-0).
If you have no experience with C (the language which underpins Objective-C), then a good book to try (with caveats, see below) is:
Kochan, S.G., Programming in Objective-C, Sams Publishing (ISBN: 0-672-32586-1).
However, a couple of words of warning. Kochan introduces Objective-C techniques using the Object root class, then switches to NSObject when discussing Foundation in section II of the book. This could lead to confusion, as the names of some selectors (e.g. protocol conformance) are different between the classes. Also, when using GNUstep, the default behaviour is a "flattened" build area; the first line of shell input on p313 of Kochan should read "cd shared_obj" instead of "cd shared_obj/ix86/mingw32/gnu-gnu-gnu".
The official c.l.o-c FAQ has a selection of references to books on Object Oriented Programming, and of course you could ask your question on comp.lang.objective-c or check the archives at Google Groups. Apple host an ObjC-language mailing list.