views:

68

answers:

4

What's the difference when using these codes:

#import <UIKit/UIKit.h>
#import "Foo.h"

@interface EditFooViewController : UIViewController {
  Foo *foo;
}
@end

and

#import <UIKit/UIKit.h>

@class Foo;

@interface EditFooViewController : UIViewController {
  Foo *foo;
}
@end
+2  A: 

I believe the answer you seek is here.

dredful
+1  A: 

The former imports a header file, Foo.h, which according to convention probably (but not necessarily) declares a class called Foo.

The latter declares that somewhere else in your code, you'll be defining a class called Foo, so it's OK to do stuff like Foo *foo;, you can take me on trust that the class Foo exists.

You tend to use @class Foo where you have circular class dependencies; i.e. where class Foo declares an instance variable of type Bar and class Bar declares an instance variable of type Foo.

Simon Whitaker
+1  A: 

The second variant forward declares Foo, which means that the compiler will know that there exists a class Foo, but nothing more about it. I.e. not the size or which members it has. For the usage here, that is not needed.

The second variant may sometimes be preferable to the first because it limits dependencies. I.e users of EditFooViewController does not need to depend on Foo.h.

harald
+1  A: 

@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;).

Daniel Dickison