Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the difference between #import and @class, and when should I use one over the other?

I've been teaching myself Objective-C over the past month or so (I'm a Java head) and I've got my brain wrapped around most of it now. One thing that's confusing me at the moment: What's the difference between importing a class via @class vs doing a #import?

Is one better than another one, or do I need to use one instead of the other in certain cases? I've been using just #import so far.

like image 339
rustyshelf Avatar asked Oct 31 '08 10:10

rustyshelf


3 Answers

#import brings the entire header file in question into the current file; any files that THAT file #imports are also included. @class, on the other hand (when used on a line by itself with some class names), just tells the compiler "Hey, you're going to see a new token soon; it's a class, so treat it that way).

This is very useful when you've got the potential for 'circular includes'; ie, Object1.h makes reference to Object2, and Object2.h makes reference to Object1. If you #importboth files into the other, the compiler can get confused as it tries to #import Object1.h, looks in it and sees Object2.h; it tries to #import Object2.h, and sees Object1.h, etc.

If, on the other hand, each of those files has @class Object1; or @class Object2;, then there's no circular reference. Just be sure to actually #import the required headers into your implementation (.m) files.

like image 153
Ben Gottlieb Avatar answered Oct 17 '22 11:10

Ben Gottlieb


@class is called a forward declaration. You're basically telling the compiler that the class exists but not anything about the class. Thus, it doesn't know stuff like its superclass and what methods it declares.

As a general rule, use @class in the .h and #import in the .m, if at all possible. Like Louis said, it'll help speed up compile times. There are times when you need to #import a class in the header, though. Cases I can think of right now are:

  • You are subclassing another class
  • You are implementing a protocol

In these cases, you must #import the header file where the class or protocol is declared because the compiler needs to know the full class hierarchy of its parent classes and implementing protocols.

FWIW, you can forward declare protocols, too, so long as your not implementing them:

@protocol SomeProtocol;

@interface ...

- (id<SomeProtocol>)someMethod;

@end
like image 32
Dave Dribin Avatar answered Oct 17 '22 11:10

Dave Dribin


The other thing you want to keep in mind is that #imports slow down your compile times, since it means the the compiler needs to pull and work through a lot more header files. This is mostly masked by the use of precompiled headers, but I have occasionally been handed projects that corss imported every header instead of using @class where appropriate, and fixing them can improve compile time. It is subtle way the the system reinforces the fact that if you only use what you actually need things go faster.

As a general rule, I always use @class declarations in in my header files, and only #import the superclass. That falls in line with Ben's suggestions, but I thought it was worth noting that even if you are not worried about circular refs it is good idea to limit #imports in header files if you can.

like image 27
Louis Gerbarg Avatar answered Oct 17 '22 11:10

Louis Gerbarg