When I compile with the following code there are no errors:
@class RootViewController;
//#import "RootViewController.h"
When I compile with the following code I get an error:
//@class RootViewController;
#import "RootViewController.h"
"error: expected specifier-qualifier-list before 'RootViewController'"
I don't understand what the difference is between the two because I used #import in a similar class and it compiled without errors!
In a nutshell, the main difference between C and C++ is that C is function-driven procedural language with no support for objects and classes, whereas C++ is a combination of procedural and object-oriented programming languages.
Object is an instance of a class. All data members and member functions of the class can be accessed with the help of objects. When a class is defined, no memory is allocated, but memory is allocated when it is instantiated (i.e. an object is created).
Difference between Structs and Classes: Struct are value types whereas Classes are reference types. Structs are stored on the stack whereas Classes are stored on the heap. Value types hold their value in memory where they are declared, but a reference type holds a reference to an object in memory.
A class defines object properties including a valid range of values, and a default value. A class also describes object behavior. An object is a member or an "instance" of a class. An object has a state in which all of its properties have values that you either explicitly define or that are defined by default settings.
@class
is used when you need to know the name of a class in a particular file, but you don't need to know any details about the class (its methods, for example). #import
is used when you actually need to use the class (i.e., send it a message).
For example, if you're declaring instance variables in a header file, you can use @class
to declare an instance variable of a certain type:
@class MyOtherClass;
@interface MyClass : NSObject
{
MyOtherClass *myIvar;
}
@end
Since you're not using myIvar
yet, you don't need to know anything about it except that the type MyOtherClass
exists.
However:
#import "MyOtherClass.h"
- (void)doSomething
{
[myIvar doSomethingElse];
}
In this case, you're sending the doSomethingElse
message to myIvar
; the compiler needs to know that instances of MyOtherClass
define this method, so you have to import the header file or the compiler will complain.
Why worry about this?
It mostly has to do with dependencies. When you #import
file A into file B, file B becomes dependent upon file A -- that is, if file A changes, you'll have to recompile file B. If you use @class
in file B, file B is not dependent on file A, and thus doesn't need to be recompiled when file A changes -- so if you're just declaring a type and not actually dependent upon the implementation of file A, you can save yourself compilation time by not #import
ing file A.
I decided to refer to the documentation because I was still confused:
#import
This directive is identical to #include, except that it makes sure that the same file is never included more than once. It’s therefore preferred and is used in place of #include in code examples throughout Objective-C–based documentation.
This convention means that every interface file includes, indirectly, the interface files for all inherited classes. When a source module imports a class interface, it gets interfaces for the entire inheritance hierarchy that the class is built upon.
@class
Declarations like this simply use the class name as a type and don’t depend on any details of the class interface (its methods and instance variables), the @class directive gives the compiler sufficient forewarning of what to expect. However, where the interface to a class is actually used (instances created, messages sent), the class interface must be imported.
http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF123
Basic rule: use @class
in you header file and #import
in your implementation file.
(However, you need to #import
your class' superclass. And in some other circumstances you also need to use `#import" in the header.)
#import
is not equivalent to #include
. If a file is included
many times, it will be loaded each time, but with many #imports
of the same file, it will still only be loaded once.
Therefore, the main reason to use @class
is not to avoid circular dependencies, but to make compilation faster.
Here's an example of when you must use @class
//MYControl.h
@class MYControl; // Must use class
@protocol MYControlDelegate
-(void)control:(MYControl *)control didChangeToState:(UIControlState)state;
@end
@interface MYControl : UIControl
{
id<MYControlDelegate> delegate_;
}
@property (nonatomic, assign) id<MYControlDelegate> delegate;
@end
//MYControl.m
@implementation MYControl
@synthesize delegate = delegate_;
. . .
In this case, there is nothing to import, because the delegate protocol is declared above the main class in the header file. But you still need to be able to refer to the main class which has not yet been declared. So what @class
does is to just let the compiler know that there is some class that is called MYControl
and will be defined at some point. (Not at runtime however. The class will be defined in the course of the compilation.)
EDIT: From the Objective-C manual:
Since declarations like this simply use the class name as a type and don’t depend on any details of the class interface (its methods and instance variables), the @class directive gives the compiler sufficient forewarning of what to expect. However, where the interface to a class is actually used (instances created, messages sent), the class interface must be imported. Typically, an interface file uses @class to declare classes, and the corresponding implementation file imports their interfaces (since it will need to create instances of those classes or send them messages).
The @class directive minimizes the amount of code seen by the compiler and linker, and is therefore the simplest way to give a forward declaration of a class name. Being simple, it avoids potential problems that may come with importing files that import still other files. For example, if one class declares a statically typed instance variable of another class, and their two interface files import each other, neither class may compile correctly.
Note that circularity is mentioned in the last sentence as one in a general class of issues dealt with by using @class
.
@class
is used to avoid circular dependency... This prevents circular references where in one header A imports a second header B which(B) imports the first(A) which imports the second (B)and so on in an endless cycle....@class
is generally used to ask compiler to look for its definition at runtime... especially when it resides in some static library..
Other than that #import
works
See this question
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With