@class Foo;
is a "forward declaration". It's useful to think about what the compiler actually sees: the compiler always compiles one .m file at a time. In your EditFooViewController.m file, you probably start off with:
#import "EditFooViewController.h"
#import "Foo.h"
So at that point, what the compiler actually sees is something like:
...the contents of UIKit.h
@class Foo;
@interface EditFooViewController : UIViewController {
Foo *foo;
@end
...the contents of Foo.h, i.e.
@interface Foo
...
@end
...the contents of your .m file.
So as you can see, you can declare the interface for EditFooViewController that references the Foo class, but it's actually defined below it when Foo.h is imported by EditFooViewController.m.
In practice, whenever your class references other classes in ivars or method declarations, you should use forward declarations (i.e. @class Foo;
).
An exception is if your class subclasses or implements a protocol, you need to actually #import
the header file that defines the protocol or superclass. This is because when a third class imports the subclass's header file, it needs the declaration for the superclass/prototype and you don't want to have to import all the superclass/prototypes' header files. This also explains why you need the #import <UIKit/UIKit.h>
at the top of the header file (as opposed to simply forward-declaring the superclass as @class UIViewController;
).