tags:

views:

131

answers:

1

I wonder about Objective-C style.

I have FooClass.[hm] that depends on BarClass.[hm] for its implementation (though not for its interface). I can #import "BarClass.h" either directly in FooClass.m or indirectly through FooClass.h. I wonder about the common choice for this.

+10  A: 

You should ALWAYS #import other classes in your .m file.

If they happen to also be members of your class, you can forward declare them (by using the @class directive) in your .h file.

The reason for doing this is because when you #import a .h file, you only want to import declarations, not definitions. By using @class and only #importing in .m files, you are a) reducing overhead and b) makes for cleaner code.

Another reason you should do it this way was pointed out by Matt Gallagher:

The reasoning behind forward declarations in header files is that it avoids unnecessary dependencies. i.e. Imagine B.h forward declares A and B.m imports A.h. Then imagine C.m, D.m, E.m and F.m import B.h. After all this is done, A.h changes. Since A is only forward declared in B.h, only B.m needs to rebuild. Without forward declarations, C.m, D.m, E.m and F.m would all need to be rebuild if A changes

Example:

.h file:

@class BarClass;

@interface FooClass : NSObject

...

@end

.m file

#import "BarClass.h"

@implementation FooClass

...

@end
Jacob Relkin
Thank you for your categorical answer. I wonder if you can elaborate on the reasoning behind this answer.
iter
The reasoning behind forward declarations in header files is that it avoids unnecessary dependencies.i.e. Imagine B.h forward declares A and B.m imports A.h. Then imagine C.m, D.m, E.m and F.m import B.h. After all this is done, A.h changes. Since A is only forward declared in B.h, only B.m needs to rebuild. Without forward declarations, C.m, D.m, E.m and F.m would all need to be rebuild if A changes.
Matt Gallagher
@Matt, you're right, i forgot about that one major point. I'll edit it in
Jacob Relkin
So it's only about building speed then?
iter
If you use a delegate as a class variable, you may have to use `#import` instead of `@class` in the header file. Other than that, this is generally good advice.
Alex Reynolds
@iter no, it's not just about build speed. It's also about circular dependencies. If A.h imports B.h and B.h imports A.h you'll get errors due to undefined references in one or other of the files.
JeremyP
Thank you for pointing out the circular dependency issue.
iter