I\'ve no idea why, but on occasion I\'ve managed to fix some compile errors, most notably
error expected specifier-qualifier-list before \'someClass\'
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.
Unless you're inheriting from the class that you're including, you shouldn't include headers in headers. If you need to include an object as an interface variable, you should use the @class
directive instead; that'll tell the compiler that the identifier refers to a class.
Instead, import headers only in implementation files. The compiler will know that your instance variables are pointers to objects, but it doesn't know the details of the object when parsing the header. All it needs to know is that it's a class. The compiler can then see the methods of the class when parsing your implementation file; at that point, it does need the class, to verify that it responds to the messages you're sending.
Update: I was going to update my answer to respond to some later questions, but Rob Napier has a good follow-up.
You'll not only include your header into your implementation file but into other files using that class as well. If you include all dependencies in the header, all other files including that header just for using the specific class it defines will themselves include all dependencies as well.
This is not only noisy but leads to problems when you have classes referencing themselves. Each class would have to be imported before the other one, which leads to one being imported first and then cannot finding the other class' type. This results in the cryptic error message you posted, which basically means that the compiler can't find the someClass
type.
By moving your imports into your implementation file and forward-declaring classes and types in your header (using @class
, @protocol
, etc) you can avoid these issues.