I haven’t been able to find a list of all Objective-C @ compiler directives in one place. We all know the keywords like @interface and @implementation but others like @dynamic and @encode are lesser known, and possibly even much less understood.

Although I know most of them already, I couldn’t shake the feeling that I may be missing a hidden gem. So I made an effort to document all the Objective-C @ compiler directives in one place.


@class

Used for class forward declarations. Declares class as known without having to import the class’ header file.

[cc lang=”c”]
@class ClassName;
[/cc]

Note, unlike with @protocol and @selector you can not write the following to get the Class object by name:
[cc lang=”cpp”]
// ERROR: this doesn’t work!
Class c = @class(ClassName);[/cc]
Instead use: [cc lang=”cpp”]Class c = [ClassName class];[/cc]


@defs

The @defs directive returns the layout of an Objective-C class, it allows you to create a C struct with the same layout as the Objective-C class. If you don’t know yet, Objective-C classes are basically just C structs with additional methods. Makes sense if you consider that Objective-C is merely a set of extensions to the C language.

[cc lang=”c”]
struct { @defs( NSObject) }
[/cc]

You will only ever need @defs for some hardcore, low-level Objective-C operations or optimizations, as in this article which speeds up Objective-C message sends.

@protocol @required @optional @end

Marks the start of a protocol declaration. A @protocol can optionally declare that it must conform to other protocols.

[cc lang=”c”]
@protocol ProtocolName
@required
// method declarations
@optional
// method declarations
@end
[/cc]

Like with @selector you can use @protocol to get a protocol object by name:

[cc lang=”c”]
-(void) aMethod
{
Protocol *aProtocol = @protocol(ProtocolName);
}
[/cc]

Dependent Directives:

  • @required (default) – Declares the methods following the @required directive as required (default).
  • @optional – Declares the methods following the @optional directive as optional. Classes implementing this protocol can decide whether to implement an optional method or not. Classes making use of the protocol must test optional protocol methods for existence. For example: [cc lang=”c”][object respondsToSelector:@selector(optionalProtocolMethod)];[/cc]
  • @end – Marks the end of the protocol declaration.

@interface @public @package @protected @private @property @end

Marks the start of a class or category declaration.

Class declaration:

While SuperClassName is optional, Objective-C classes should derive from NSObject either directly or indirectly. The @interface for a class declaration can optionally declare that it conforms to other protocols.

[cc lang=”c”]
@interface ClassName : SuperClassName
{
@public
// instance variables
@package
// instance variables
@protected
// instance variables
@private
// instance variables
}

// property declarations
@property (atomic, readwrite, assign) id aProperty;

// public instance and/or class method declarations
@end
[/cc]

Category declaration:

The @interface of a Objective-C category can not add instance variables. But it can optionally declare to conform to (additional) protocols. CategoryName can be omitted (leaving only the empty brackets) if the category is added to the implementation file of the class that it extends, in order to declare methods as “private”.

[cc lang=”c”]
@interface ClassName (CategoryName)

// property declarations
@property (atomic, readwrite, assign) id aProperty;

// method declarations
@end
[/cc]

Dependent Directives:

  • @public – Declares the instance variables following the @public directive as publicly accessible. Public instance variables can be read and modified with pointer notation: [cc lang=”cpp”]someObject->aPublicVariable = 10;[/cc]
  • @package – Declares the instance variables following the @package directive as public inside the framework that defined the class, but private outside the framework. This applies only to 64-bit systems, on 32-bit systems @package has the same meaning as @public.
  • @protected (default) – Declares the instance variables following the @protected directive as accessible only to the class and its derived classes.
  • @private – Declares the instance variables following the @private directive as private to the class. Not even derived classes can access private instance variables.
  • @property – Declares a property which can be accessed with dot notation. The @property can be followed by optional brackets within which special keywords (property modifiers) specify the exact behavior of the property. The property modifiers are:
    • readwrite (default), readonly – Generate both setter & getter methods (readwrite), or only the getter method (readonly).
    • assign (default), retain, copy – Only applicable for properties that can be safely cast to id. Assign simply assigns the passed value – retain sends release to the existing instance variable, sends retain to the new object, assigns the retained object to the instance variable – copy sends release to the existing instance variable, sends copy to the new object, assigns the copied object to the instance variable. In the latter two cases you are still responsible for sending release (or assigning nil) to the property on dealloc.
    • atomic (default), nonatomic – Atomic properties are thread-safe, nonatomic properties are prone to synchronization issues if accessed from multiple threads. Nonatomic property access is faster than atomic and often used in single-threaded apps, or in cases where you’re absolutely sure the property will only be accessed from one thread.
    • weak (default), strong – Available if automatic reference counting (ARC) is enabled. The keyword strong is synonymous to retain, while weak is synonymous to assign, except that a weak property is automatically set to nil should the instance be deallocated. Note that weak is only available in iOS 5 or newer and Mac OS X 10.7 (Lion) or newer.
  • @end – Marks the end of the interface declaration.

@implementation @synthesize @dynamic @end

Marks the start of a class’ or category implementation.

Class implementation:
[cc lang=”c”]
@implementation ClassName
@synthesize aProperty, bProperty;
@synthesize cProperty=instanceVariableName;
@dynamic anotherProperty;

// method implementations
@end
[/cc]

Category implementation:
[cc lang=”c”]
@implementation ClassName (CategoryName)
@synthesize aProperty, bProperty;
@synthesize cProperty=instanceVariableName;
@dynamic anotherProperty, bnotherProperty;

// method implementations
@end
[/cc]

Dependent Directives:

  • @synthesize – Instruct compiler to automatically generate property setter and getter methods for the given (comma seperated list of) properties. The setter and getter methods are generated according to the property modifiers. If the instance variable is not named exactly like the @property, you can specify the instance variable name following the equals sign.
  • @dynamic – Tells the compiler that the necessary setter and getter methods for the given (comma seperated list of) properties will be implemented manually, or dynamically at runtime. Accessing a dynamic property will not generate a compiler warning, even if the getter/setter is not (yet) implemented. You will want to use @dynamic in cases where property getter and setter methods need to perform custom code.
  • @end – Marks the end of the implementation of the class.

@throw @try @catch @finally

Used for handling and throwing exceptions.

Throwing and Handling exceptions:
[cc lang=”c”]
@try
{
// code that might throw an exception … like this one:
NSException *exception =
[NSException exceptionWithName:@”ExampleException”
reason:@”In your face!”
userInfo:nil];
@throw exception;
}
@catch (CustomException *ce)
{
// CustomException-specific handling …
}
@catch (NSException *ne)
{
// generic NSException handling …

// to simply re-throw the caught exception in a catch block:
@throw;
}
@finally
{
// code that runs whether an exception occurred or not …
}
[/cc]


@synchronized

Encapsulates code in a mutex lock. It ensures that the block of code and the locked object can only be accessed by one thread at a time. See mutual exclusion.

[cc lang=”c”]
-(void) aMethodWithObject:(id)object
{
@synchronized(object)
{
// code that works with locked object
}
}
[/cc]


@autoreleasepool

In an app that has ARC (automatic reference counting) enabled, you must use @autoreleasepool as a replacement for the NSAutoreleasePool class. The @autoreleasepool is about six times faster than using NSAutoreleasePool, therefore Apple recommends its use even for non-ARC projects.

You should not declare a variable inside the @autoreleasepool block and continue to use the variable after the @autoreleasepool block. Such code should be avoided or refactored.

[cc lang=”c”]
-(void) aMethod
{
@autoreleasepool
{
// code that creates a large number of temporary objects
}
}
[/cc]


@selector

Returns the selector type SEL of the given Objective-C method. Generates compiler warning if the method isn’t declared or doesn’t exist.

[cc lang=”c”]
-(void) aMethod
{
SEL aMethodSelector = @selector(aMethod);
[self performSelector:aMethodSelector];
}
[/cc]


@encode

Returns the character string encoding of a type.

[cc lang=”c”]
-(void) aMethod
{
char *enc1 = @encode(int); // enc1 = “i”
char *enc2 = @encode(id); // enc2 = “@”
char *enc3 = @encode(@selector(aMethod)); // enc3 = “:”

// practical example:
CGRect rect = CGRectMake(0, 0, 100, 100);
NSValue *v = [NSValue value:&rect withObjCType:@encode(CGRect)];
}
[/cc]


@compatibility_alias

Allows you to define an alias name for an existing class. The first parameter is the alias for a class name, a class with this name must not exist. The second parameter is the name of an existing class that the alias refers to.

[cc lang=”c”]
@compatibility_alias AliasClassName ExistingClassName
[/cc]

From then on you can use AliasClassName in place of ExistingClassName. This can be useful after refactoring a class’ name without modifying its behavior, you can use @compatibility_alias to allow existing code using the refactored class to continue to work without refactoring.

@”string”

Declares a constant NSString object. Such strings do not need to be retained or released.

[cc lang=”c”]
-(void) aMethod
{
NSString* str = @”This is a constant string.”;
NSUInteger strLength = [@”This is legal!” length];
}
[/cc]

Summary

I hope you enjoyed this list and hopefully learned something from it. If you know there’s a directive missing from the list, please add a comment and I will update the post!

UPDATE: Johann Dowa from maniacdev.com has compiled the Objective-C 2.0 @ Compiler Directives Cheat Sheet in PDF format.

If you liked this list please tweet, like or plus-one it, thank you!


This article was brought to you by ...

I very much enjoy the learning process, the pushing of boundaries (mine and yours and that of technology), having the freedom to pursue whatever is on my mind, to boldly program what no one has programmed before, and to write about what I've learned. Help me help you by browsing the products in the Learn Cocos2D Store.

28 Responses to “The Complete List of Objective-C 2.0 @ Compiler Directives”

  1. Paolo says:

    Actually, the Objective-C reference reports:
    By default, all unmarked instance variables […] are @protected.

    You may want to correct that

  2. CrizZ says:

    Thanks for this overview! That’s really helpfull for me 😀

  3. Dave says:

    There’s one more that I know of: @compatibility_alias. It’s used for creating aliases for classes. http://developer.apple.com/legacy/mac/library/#documentation/DeveloperTools/gcc-3.3/gcc/compatibility_005falias.html

  4. Karoly says:

    You missed one: @compatibility_alias can be used to define class name equivalents.

  5. iWyre says:

    […] 2.0 Compiler Directives by admin on October 20th, 2011 Steffen Itterheim has posted a really nice list of all the Objective-C 2.0 compiler directives along with examples of how to use […]

  6. Ben says:

    You don’t need @dynamic if you manually implement the property – it’s only needed for dynamically generated implementations.

  7. A question actually: so you get Protocol *aProtocol = @protocol(ProtocolName); what can you do with it? Is there any real-life usage of protocol instances?

    • If it hadn’t any use it wouldn’t exist. 😉
      For example to check if an object conforms to a protocol. You can then cast it to an object conforming to that protocol so that you can call protocol methods on it, without having to know which kind of class the object is:

      Protocol *aProtocol = @protocol(ProtocolName);
      if ([sender conformsToProtocol:aProtocol])
      {
         id<ProtocolName> senderWithProtocol = (id<ProtocolName>)sender;
         BOOL wtf = [senderWithProtocol aProtocolMethod];
      }
      

      See NSObject protocol reference.

  8. Damien says:

    Nice!

    Not sure about @synthesize in category implementations though.. Even if you can still write custom getters and setters and provide specific storage for the variable yourself.

  9. Steve Weller says:

    Another use of @dynamic and @property is in a subclass. You override, but want access to an ivar declared in the superclass implementation file without referencing it directly, so create the property you want, but then keep the compiler from complaining that there is no storage with @dynamic.

  10. […] which will plot a single point from latitude and longitude coordinates and zoom to that position. 8. The Complete List of Objective-C 2.0 @ Compiler DirectivesFull list of all Objective-C @ compiler directives in one place. 9. Localizing your iPhone […]

  11. […] Complete List of Objective-C 2.0 compiler directives. […]

  12. […] 全文可以看The Complete List of Objective-C 2.0 @ Compiler Directives 4.Mac Objective-C […]

  13. […] The Complete List of Objective-C 2.0 Compiler Directives […]

  14. […] Itterheim has compiled a complete list of those Objective-C @ compiler directives: I haven’t been able to find a list of […]

  15. Jason Coleman says:

    Thanks a lot. Really appreciate the effort.

  16. laxman says:

    thanks…it was real helpful

  17. Alex says:

    Hey, Steffen

    A very nice compilation of objc @-directives. One point that I think is not made clear enough is that @autoreleasepool is not directly related to ARC, it is a separate feature of LLVM Compiler 3.0.

    Reference –> http://stackoverflow.com/a/7950636/213682
    > you may use @autoreleasepool regardless of ARC,
    > and it’ll be faster than NSAutoreleasePool on
    > OS X v10.7+ and iOS 5.0+.

    Best regards
    Alex

  18. […] weak (default), strong – Available if automatic reference counting (ARC) is enabled. The keyword strong is synonymous to retain , while weak is synonymous to assign , except that a weak property is automatically set to nil should the instance be deallocated. Note that weak is only available in iOS 5 or newer and Mac OS X 10.7 (Lion) or newer. The Complete List of Objective-C 2.0 @ Compiler Directives | Learn & Master Cocos2D Game Develop… […]

  19. […] Itterheim has posted a really nice list of all the Objective-C 2.0 compiler directives along with examples of how to use […]

  20. Reid Ellis says:

    Any chance of an update with all the new @literals? e.g.:
    NSArray * arr = @[@”hello”, @”world”, @42];