Where/when to #import

  • Hi-

    Could someone point me to where I learn all the proper rules about
    where and when to #import (and also @class)?

    I have searched for this but haven't found it.

    My history with importing is mostly to try to follow examples and/or
    try things until they work.

    Currently here are the rules in my head, which might not be correct:

    1. put #import <Cocoa/Cocoa.h> in each class' .h file
    2. put a @class in the .h file for each class about which the
    compiler complains
    3. put #import "MyClass.h" in the MyClass.m file
    4. put #import "MyOtherClass.h" in the MyClass.m file for each class
    about which the compiler complains

    I had been using these rules which seemed to be cleaner to me but ran
    afoul of all the sample code I found, so I've been moving away from
    them:

    1. put #import <Cocoa/Cocoa.h> in each class' .h file
    2. put #import "MyClass.h" in the MyClass.m file
    3. put #import "MyOtherClass.h" in the *MyClass.h* file for each
    class about which the compiler complains

    This made sense to me because then each .h file knew about a lot more
    of my other classes and I didn't really ever have to use @class. And
    since my understanding of #import is that the compiler only imports
    each file once, there is no danger of redundant copying of headers.
    But as I said, this does not seem to be the correct way to do it.

    Can anyone enlighten me? Thank you.
  • Hi Paul,

    Here are the rules that I follow which seems to work very well for me:

    (1) #import <Cocoa/Cocoa.h goes in your class's .h file.
    (2) Use @class only in your .h files for all of your class references
    used (unless you derived your class from another class, in which you
    need to use the #import directive, because the compiler needs to know
    everything about the original class when you derive.)
    (3) Place all other #import directives in your .m files.

    I haven't encountered any problems yet using these rules.  Hope that
    helps!
    Nelson Santos

    On Oct 9, 2007, at 9:09 AM, Paul Bruneau wrote:

    > Hi-
    >
    > Could someone point me to where I learn all the proper rules about
    > where and when to #import (and also @class)?
    >
    > I have searched for this but haven't found it.
    >
    > My history with importing is mostly to try to follow examples and/
    > or try things until they work.
    >
    > Currently here are the rules in my head, which might not be correct:
    >
    > 1. put #import <Cocoa/Cocoa.h> in each class' .h file
    > 2. put a @class in the .h file for each class about which the
    > compiler complains
    > 3. put #import "MyClass.h" in the MyClass.m file
    > 4. put #import "MyOtherClass.h" in the MyClass.m file for each
    > class about which the compiler complains
    >
    >
    > I had been using these rules which seemed to be cleaner to me but
    > ran afoul of all the sample code I found, so I've been moving away
    > from them:
    >
    > 1. put #import <Cocoa/Cocoa.h> in each class' .h file
    > 2. put #import "MyClass.h" in the MyClass.m file
    > 3. put #import "MyOtherClass.h" in the *MyClass.h* file for each
    > class about which the compiler complains
    >
    > This made sense to me because then each .h file knew about a lot
    > more of my other classes and I didn't really ever have to use
    > @class. And since my understanding of #import is that the compiler
    > only imports each file once, there is no danger of redundant
    > copying of headers. But as I said, this does not seem to be the
    > correct way to do it.
    >
    > Can anyone enlighten me? Thank you.
  • Le 9 oct. 07 à 15:41, Nelson Santos a écrit :

    > Hi Paul,
    >
    > Here are the rules that I follow which seems to work very well for me:
    >
    > (1) #import <Cocoa/Cocoa.h goes in your class's .h file.
    > (2) Use @class only in your .h files for all of your class
    > references used (unless you derived your class from another class,
    > in which you need to use the #import directive, because the
    > compiler needs to know everything about the original class when you
    > derive.)
    > (3) Place all other #import directives in your .m files.

    I'm using this too, because I was stung with a cross-reference one
    time and discovered I was doing wrong (I was #import'ing everything
    in *.h files)... Another little addition, if you're building a
    framework :
    It's better to use #import <framework/file.h> syntax in your public
    API headers, so that someone including your framework don't need to
    add an unnecessary include path to their project... (I had problem
    with this in the past, but I can't remember how...)

    Etienne Samson
  • > Hi-
    >
    > Could someone point me to where I learn all the proper rules about where and when to #import (and also @class)?
    >
    > I have searched for this but haven't found it.
    >
    > My history with importing is mostly to try to follow examples and/or try things until they work.
    >
    > Currently here are the rules in my head, which might not be correct:
    >
    > 1. put #import <Cocoa/Cocoa.h>  in each class' .h file
    > 2. put a @class in the .h file for each class about which the compiler complains
    > 3. put #import "MyClass.h" in the MyClass.m file
    > 4. put #import "MyOtherClass.h" in the MyClass.m file for each class about which the compiler complains
    >
    >
    > I had been using these rules which seemed to be cleaner to me but ran afoul of all the sample code I found, so I've been moving away from them:
    >
    > 1. put #import <Cocoa/Cocoa.h>  in each class' .h file
    > 2. put #import "MyClass.h" in the MyClass.m file
    > 3. put #import "MyOtherClass.h" in the *MyClass.h* file for each class about which the compiler complains

    There are actually two reasons I know about why you may want to use @class (that is, a forward declaration) instead of #import if possible:

    - To avoid circular references (as Etienne points out in his answer), which is a rare problem.

    - To minimize imports in headers in order to speed up compiles. Whatever you import in a header file becomes effectively an import in every other file which uses this header and such any change in the imported header triggers rebuild of any file which imports the importing header. Depending on your project size, the difference in rebuild times can be substantial.

    My rule is therefore to prefer @class where possible in headers.

    Cheers,
    Kai

    >
    > This made sense to me because then each .h file knew about a lot more of my other classes and I didn't really ever have to use @class. And since my understanding of #import is that the compiler only imports each file once, there is no danger of redundant copying of headers. But as I said, this does not seem to be the correct way to do it.
    >
    > Can anyone enlighten me? Thank you.
  • Thanks to everyone for your notes. I think I have a clearer picture
    of #import now.
  • Hi Paul,

    On 2007-10-10, at 00:55, Kai Brüning wrote:

    > There are actually two reasons I know about why you may want to use
    > @class (that is, a forward declaration) instead of #import if
    > possible:
    >
    > - To avoid circular references (as Etienne points out in his
    > answer), which is a rare problem.

    Indeed. The whole point of using #import instead of #include is to
    have the compiler avoid circular references automatically. It does
    this by not re-including a file if another of that name has already
    been imported.

    You can still get duplicate imports if, for example, you have a
    structure like:

    // ClassA.h
    #import "other/ClassB.h"
    #import "ClassC.h"

    // ClassC.h
    #import "ClassB.h"

    Since it only works on the path level, ClassB.h would be included
    twice (which would likely lead to errors).

    But in more recent versions of Xcode, this is mostly a moot point,
    since you don't usually have to specify a path to a file -- Xcode will
    put all the directories containing headers on the include path
    automatically.

    > - To minimize imports in headers in order to speed up compiles.

    This is the real reason you'd want to use @class instead of #include.

    If I may tweak Nelson's rules:

    1. Generally, #import <Cocoa/Cocoa.h> in your class interface files.
    For model classes that you might want to use in non-GUI situations
    (e.g. Spotlight importer), you can instead just #import <Foundation/
    Foundation.h>.

      (Importing Cocoa.h is shorthand for importing Foundation+AppKit
    +CoreData.)

    2. If your class interface refers to other classes that aren't in the
    frameworks (such as in instance variables, or method parameters and
    return types), forward-declare those classes with @class.

    3. If your class is a subclass of a non-framework class, you must
    #import the superclass's header.

    4. In your implementation file, #import the interface, and #import the
    interfaces of any other classes whose methods you call.

    The situation you want to avoid is this. Say you have a class that is
    used by many other source files in your program (CommonClass), and its
    interface #imports a little helper class (HelperClass). If you tweak
    HelperClass.h (re-order instance variables, or even just add a
    comment), then that will flow on to CommonClass.h, which will then
    flow on to the hundreds of other files that include the common class
    (making the build take a long time). Instead, the /implementation/
    CommonClass.m should #import HelperClass.h, and CommonClass.h should
    just @class HelperClass.

    And I've written a bit too much now.

    Jonathon Mah
    <me...>
  • Uh Oh...

    I've been reading this thread and I just realized that I must be
    doing it all wrong....

    I have several custom class.....

    ClassA
    ClassB
    ClassC

    and in my MainController.h file I have imported all of them via
    "#import <classname>.h"

    How exactly should I really be doing it?

    On Oct 9, 2007, at 1:43 PM, Jonathon Mah wrote:

    > Hi Paul,
    >
    > On 2007-10-10, at 00:55, Kai Brüning wrote:
    >
    >> There are actually two reasons I know about why you may want to
    >> use @class (that is, a forward declaration) instead of #import if
    >> possible:
    >>
    >> - To avoid circular references (as Etienne points out in his
    >> answer), which is a rare problem.
    >
    > Indeed. The whole point of using #import instead of #include is to
    > have the compiler avoid circular references automatically. It does
    > this by not re-including a file if another of that name has already
    > been imported.
    >
    > You can still get duplicate imports if, for example, you have a
    > structure like:
    >
    > // ClassA.h
    > #import "other/ClassB.h"
    > #import "ClassC.h"
    >
    > // ClassC.h
    > #import "ClassB.h"
    >
    > Since it only works on the path level, ClassB.h would be included
    > twice (which would likely lead to errors).
    >
    > But in more recent versions of Xcode, this is mostly a moot point,
    > since you don't usually have to specify a path to a file -- Xcode
    > will put all the directories containing headers on the include path
    > automatically.
    >
    >> - To minimize imports in headers in order to speed up compiles.
    >
    > This is the real reason you'd want to use @class instead of #include.
    >
    > If I may tweak Nelson's rules:
    >
    > 1. Generally, #import <Cocoa/Cocoa.h> in your class interface
    > files. For model classes that you might want to use in non-GUI
    > situations (e.g. Spotlight importer), you can instead just #import
    > <Foundation/Foundation.h>.
    >
    > (Importing Cocoa.h is shorthand for importing Foundation+AppKit
    > +CoreData.)
    >
    >
    > 2. If your class interface refers to other classes that aren't in
    > the frameworks (such as in instance variables, or method parameters
    > and return types), forward-declare those classes with @class.
    >
    >
    > 3. If your class is a subclass of a non-framework class, you must
    > #import the superclass's header.
    >
    >
    > 4. In your implementation file, #import the interface, and #import
    > the interfaces of any other classes whose methods you call.
    >
    >
    > The situation you want to avoid is this. Say you have a class that
    > is used by many other source files in your program (CommonClass),
    > and its interface #imports a little helper class (HelperClass). If
    > you tweak HelperClass.h (re-order instance variables, or even just
    > add a comment), then that will flow on to CommonClass.h, which will
    > then flow on to the hundreds of other files that include the common
    > class (making the build take a long time). Instead, the /
    > implementation/ CommonClass.m should #import HelperClass.h, and
    > CommonClass.h should just @class HelperClass.
    >
    >
    > And I've written a bit too much now.
    >
    >
    >
    > Jonathon Mah
    > <me...>
  • Hi Tim,

    I would move those three #import directives into the controller's .m
    file.  UNLESS, your controller is derived from one of those custom
    classes, in which case, you would need the #import directive of the
    parent class in the controller's .h file, and the other 2 can still
    go in the .m file.

    Nelson Santos

    On Oct 9, 2007, at 3:41 PM, Tim Davis wrote:

    > Uh Oh...
    >
    > I've been reading this thread and I just realized that I must be
    > doing it all wrong....
    >
    > I have several custom class.....
    >
    > ClassA
    > ClassB
    > ClassC
    >
    > and in my MainController.h file I have imported all of them via
    > "#import <classname>.h"
    >
    > How exactly should I really be doing it?
    >
    > On Oct 9, 2007, at 1:43 PM, Jonathon Mah wrote:
    >
    >> Hi Paul,
    >>
    >> On 2007-10-10, at 00:55, Kai Brüning wrote:
    >>
    >>> There are actually two reasons I know about why you may want to
    >>> use @class (that is, a forward declaration) instead of #import if
    >>> possible:
    >>>
    >>> - To avoid circular references (as Etienne points out in his
    >>> answer), which is a rare problem.
    >>
    >> Indeed. The whole point of using #import instead of #include is to
    >> have the compiler avoid circular references automatically. It does
    >> this by not re-including a file if another of that name has
    >> already been imported.
    >>
    >> You can still get duplicate imports if, for example, you have a
    >> structure like:
    >>
    >> // ClassA.h
    >> #import "other/ClassB.h"
    >> #import "ClassC.h"
    >>
    >> // ClassC.h
    >> #import "ClassB.h"
    >>
    >> Since it only works on the path level, ClassB.h would be included
    >> twice (which would likely lead to errors).
    >>
    >> But in more recent versions of Xcode, this is mostly a moot point,
    >> since you don't usually have to specify a path to a file -- Xcode
    >> will put all the directories containing headers on the include
    >> path automatically.
    >>
    >>> - To minimize imports in headers in order to speed up compiles.
    >>
    >> This is the real reason you'd want to use @class instead of #include.
    >>
    >> If I may tweak Nelson's rules:
    >>
    >> 1. Generally, #import <Cocoa/Cocoa.h> in your class interface
    >> files. For model classes that you might want to use in non-GUI
    >> situations (e.g. Spotlight importer), you can instead just #import
    >> <Foundation/Foundation.h>.
    >>
    >> (Importing Cocoa.h is shorthand for importing Foundation+AppKit
    >> +CoreData.)
    >>
    >>
    >> 2. If your class interface refers to other classes that aren't in
    >> the frameworks (such as in instance variables, or method
    >> parameters and return types), forward-declare those classes with
    >> @class.
    >>
    >>
    >> 3. If your class is a subclass of a non-framework class, you must
    >> #import the superclass's header.
    >>
    >>
    >> 4. In your implementation file, #import the interface, and #import
    >> the interfaces of any other classes whose methods you call.
    >>
    >>
    >> The situation you want to avoid is this. Say you have a class that
    >> is used by many other source files in your program (CommonClass),
    >> and its interface #imports a little helper class (HelperClass). If
    >> you tweak HelperClass.h (re-order instance variables, or even just
    >> add a comment), then that will flow on to CommonClass.h, which
    >> will then flow on to the hundreds of other files that include the
    >> common class (making the build take a long time). Instead, the /
    >> implementation/ CommonClass.m should #import HelperClass.h, and
    >> CommonClass.h should just @class HelperClass.
    >>
    >>
    >> And I've written a bit too much now.
    >>
    >>
    >>
    >> Jonathon Mah
    >> <me...>

previous month october 2007 next month
MTWTFSS
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Go to today