Cocoa: What is the difference between importing in the header and importing into the main file?

I have no idea why, but sometimes I managed to fix compilation errors, especially

error expected specifier-qualifier-list before 'someClass' 

moving #import "someClass.h" from the .h file to the .m file. It also worked with several other issues that I ran into that were (mysteriously from my point of view) related to the headers.

Some quick googling included the answer "never import headers into a header file" and where the tip stops.

Either I did it completely, or I was used to something, but I thought that the heading should be so that the headings are meant to be imported. Obviously not, but can someone explain to me why this is, and what is the preferred way to import the headers?

+7
import objective-c header cocoa
source share
3 answers

Unless you inherit the class that you included, you should not include headers in headers. If you need to include an object as an interface variable, you should use @class instead; which tells the compiler that the identifier belongs to the class.

Instead, import headers only into implementation files. The compiler will know that your instance variables are pointers to objects, but when parsing the header, they do not know the details of the object. All you need to know is that it is a class. Then the compiler can see the class methods when parsing your implementation file; at this point, he needs a class to make sure he is responding to messages you send.


Update: I was about to update my answer to answer some later questions, but Rob Napier has a good sequel .

+10
source share

John gives good advice, but here is a bit more background on whys, wherefores and exceptions.

There are two goals to avoid importing headers into headers: improved incremental build times and avoiding circular dependencies. If you import Ah into Bh and import Bh into Ch , then every time you change something in Ah , you need to recompile Cm , even if Cm does not use any of the things defined in Ah . This can lead to a really terrible and unnecessary build failure, especially if you have headers that change frequently (as is common in the early stages of development).

The first goal is commendable, but for small projects, who cares? You have 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. Ah references class B and Bh refer to class A This can actually happen quite often and can infiltrate the system completely innocently. A collection object can refer to the type of objects that it contains, and objects can refer to a type of a collection object. All that is required is a single reference due to some method that accepts or returns this type. If you have headers importing other headers, the likelihood of this quickly approaches unity. You complete the recursive import, and compile-time errors can be blurry. "I know that typdef is defined! It's right here! It's imported!" But it was not parsed when you imported this header. This is what causes the error above.

For this reason, even if you don’t have so much about build time (although you need it), avoid importing headers into headers ... except ....

Some headers to import. Of course, your superclass. Files that define @protocol that you implement, or typedef that you use. So yes, you must enable them.

What about system headers? Well, they are never going to cause rejection, and, obviously, they will not cause recursive imports, so everything is in order. I discourage people from using @class advanced ads for things in the system headers. This creates an extra user experience for your title without any value. For good heading hygiene, please remember to include system headings in <angle brackets> and your headings in quotation marks.

So this is not a trivial question, but a simple rule: avoid importing user headers into other user headers anytime the compiler allows you.

+13
source share

You not only include the header in your implementation file, but also in other files using this class. If you include all the dependencies in the header, all other files, including this header, only to use the specific class that it defines will themselves include all the dependencies.

This is not only noisy, but also leads to problems when you have classes referencing yourself. Each class must be imported before the other, which leads to the fact that it is imported first and then cannot find the type of another class. This results in an error message, which basically means that the compiler cannot find the type someClass .

By moving your import to your implementation file and reselling the class and type declarations in the header (using @class , @protocol , etc.), you can avoid these problems.

0
source share

All Articles