John gives good advice, but here is a bit more background on the whys, wherefores and exceptions.
There are two goals behind avoiding importing headers into headers: improved incremental build times and the avoidance of circular dependencies. If you import A.h
into B.h
and import B.h
into C.h
, then every time you change anything in A.h
, you have to recompile C.m
, even if C.m
makes no use of any of the things defined in A.h
. This can lead to really terrible and unnecessary build-churn, especially if you have headers that change often (as is common in the early stages of development).
The first goal is laudable, but for smallish projects, who cares? You've got a quad-core Pro and a complete build takes a couple of minutes, right? But you still have to worry about the second problem: circular dependencies. A.h
references class B
and B.h
references class A
. This actually can happen quite often and can creep into a system quite innocently. A collection object might reference the type of the objects it contains, and the objects might reference the type of the collection object. All it takes is a single reference because of some method that takes or returns that type. If you have headers importing other headers, the likelihood of this happening rapidly approaches unity. You wind up with recursive imports, and the compile-time errors can be mind-blowing. "I know that typdef is defined! It's right there! It's imported!" But, it wasn't parsed yet when you imported this header. This is what's causing your error above.
For this reason, even if you don't care that much about build times (though you should), avoid importing headers into headers... except....
Some headers you have to import. Your superclass of course. Files that define a @protocol
you implement or typedef
you use. So yeah, you have to include those.
And what about system headers? Well, they're never going to cause churn, and obviously they're not going to cause recursive imports, so they're fine. I discourage folks from using @class
forward declarations for things in system headers. It creates extra work on the user of your header for no value. For good header hygiene, please remember to enclose system headers in <angle brackets> and your headers in "quotation marks".
So it's not a trivial question, but the simple rule is: avoid importing user headers into other user headers anytime the compiler will let you.