24

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.

iter
  • 4,171
  • 8
  • 35
  • 59

2 Answers2

50

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
Community
  • 1
  • 1
Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320
  • 2
    Thank you for your categorical answer. I wonder if you can elaborate on the reasoning behind this answer. – iter May 05 '10 at 03:02
  • 6
    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 May 05 '10 at 04:31
  • @Matt, you're right, i forgot about that one major point. I'll edit it in – Jacob Relkin May 05 '10 at 04:34
  • So it's only about building speed then? – iter May 05 '10 at 04:35
  • 1
    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 May 05 '10 at 04:39
  • 1
    @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 May 05 '10 at 14:18
  • And what about protocols ? Should they be imported in .h file or .m file ? – Arnaud Jul 18 '13 at 05:01
  • I'm very confused by this answer. I am using an instance of a class I created (Level) as a @property of my other class, GameController. If I remove the `#import "Level.h"` from the header file and place it in the implementation file, the property declaration gives an error. What am I misunderstanding about your explanation? Is this where I should be using forward declarations? – temporary_user_name Nov 15 '14 at 02:10
  • What does "If they happen to also be members of your class, you can forward declare them (by using the @class directive) in your .h file" mean? How is a class a 'member' of another class? – cheznead May 30 '17 at 17:30
0

#import in .h or .m files

  • .h file - public interface of a class
  • .m file - private implementation of the class

My rules are:

  • Forward declaration[About] - @class inside .h file
  • You should reduce of imports in .h
  • The accent should be on import in .m file that prevents dependency issues

When you need something in implementation then you should import it in .m. When you need something in interface then you should import it in .h.

[import angle brackets <> and quote marks ""]

yoAlex5
  • 29,217
  • 8
  • 193
  • 205