Basic rule: use @class
in you header file and #import
in your implementation file.
(However, you need to #import
your class' superclass. And in some other circumstances you also need to use `#import" in the header.)
#import
is not equivalent to #include
. If a file is included
many times, it will be loaded each time, but with many #imports
of the same file, it will still only be loaded once.
Therefore, the main reason to use @class
is not to avoid circular dependencies, but to make compilation faster.
Here's an example of when you must use @class
//MYControl.h
@class MYControl; // Must use class
@protocol MYControlDelegate
-(void)control:(MYControl *)control didChangeToState:(UIControlState)state;
@end
@interface MYControl : UIControl
{
id<MYControlDelegate> delegate_;
}
@property (nonatomic, assign) id<MYControlDelegate> delegate;
@end
//MYControl.m
@implementation MYControl
@synthesize delegate = delegate_;
. . .
In this case, there is nothing to import, because the delegate protocol is declared above the main class in the header file. But you still need to be able to refer to the main class which has not yet been declared. So what @class
does is to just let the compiler know that there is some class that is called MYControl
and will be defined at some point. (Not at runtime however. The class will be defined in the course of the compilation.)
EDIT: From the Objective-C manual:
Since declarations like this simply
use the class name as a type and don’t
depend on any details of the class
interface (its methods and instance
variables), the @class directive gives
the compiler sufficient forewarning of
what to expect. However, where the
interface to a class is actually used
(instances created, messages sent),
the class interface must be imported.
Typically, an interface file uses
@class to declare classes, and the
corresponding implementation file
imports their interfaces (since it
will need to create instances of those
classes or send them messages).
The @class directive minimizes the
amount of code seen by the compiler
and linker, and is therefore the
simplest way to give a forward
declaration of a class name. Being
simple, it avoids potential problems
that may come with importing files
that import still other files. For
example, if one class declares a
statically typed instance variable of
another class, and their two interface
files import each other, neither class
may compile correctly.
Note that circularity is mentioned in the last sentence as one in a general class of issues dealt with by using @class
.