Composition: use @class or #import?

5

I recently had a problem with Unknow type name 'Class' because I was doing import in the header of 2 classes. I discovered that this is a classic headers error importing headers .

I was directed to change the import of one of the classes to @class and in the implementation class (.m) to do the import.

My question is: when to use @class or #import ? I could delete the imports of all my classes that refer to other classes and simply write @class and then import them into the implementation file ?

    
asked by anonymous 03.02.2014 / 15:08

3 answers

4

Here is a summary answer (not 100% correct). This subject is quite extensive to explain in a post, if you are not satisfied you will have to be researching to deepen the question. I just want to give you a simple idea, I advise you to go into it further.

But first, I'm going to assume you do not know C and give a brief explanation on how the code is made into an app.

We can say that there are 3 steps (actually more, but knowing these three is enough to get a good idea of the process):

1) Pre-build

This is when the code is prepared for compilation, when the #define , #ifdef , and so on directives are used. are processed. That is, if we have a #define MyDef 3 , at the end of this step all the code sites with MyDef will have 3.

This step also manages macros, for example, if we have the files a.h

#define MyDef 3

and b.h

#define MyDef 4

When we use MyDef , its value will depend on the order in which we include headers .

#import "a.h"
#import "b.h"
// MyDef == 4

#import "b.h"
#import "a.h"
// MyDef == 3

2) Compilation

This is the sum of the whole process, that's why it's called compilation also the three steps together, because this is the main one.

This step transforms the code into machine language. This step results in binary files as executable code. It has the bytes that the processor will interpret during execution to know what to do.

These partial binaries also have references to the other partial binaries and iOS libraries (the .framework).

3) Linking

This is the last step. This is when all the partial binaries resulting from 2 are put together into one executable.

It is also here that features are added to the final binary.

When using the @class directive, we are telling the compiler that the class exists and does not need to check its existence, delegating this check to linking .

For example:

@class XPTO;
@interface YPTO : NSObject
    @property (strong, nonatomic) XPTO *xpto;
    //...
@end

This .h tells the compiler not to worry about XPTO this will be treated in linking .

This has a problem, not having a reference to the class, the compiler does not know how to use it. Therefore, in% with% we add .m :

#import "YPTO.h"
#import "XPTO.h"
@implementation YPTO
    - (void)yMethod
    {
        [xpto xMethod];
    }
    //...
@end

Without #import , the compiler does not know the reference of the #import method to use when creating the partial binary of the YPTO. This can be seen as follows. The xMethod directive creates the references, if the compiler does not read @interface does not know which references to use.

What happens is that the compiler (and also the precompiler) when it traverses @interface will i) read YPTO.m , ii) read the YPTO.h and ii) read XPTO.h .

  

When using @implementation YPTO or @class ?

Use #import when you do not need @class .

Personally, I try to have as few as% of% s in% as possible%. Using the example of the XPTO and YPTO classes. Imagine that we later created a ZPTO class that uses the YPTO, but does not need the XPTO. When we do #import , the compiler will not waste time reading #import nor .h s from it.

Another advantage is that we reduce the possibility of having, for example

a.h

#import "b.h"

b.h

#import "a.h"

When reading #import "YPTO.h" , the compiler would read XPTO,h , which would in turn make the compiler read #import , a.h , b.h , ad infinitum .

  

I could delete the imports of all my classes that refer to other classes and simply write a.h and then import them into the implementation file p>

I'm going to assume that when you say delete classes you mean b.h .

The answer seems to be "yes, you can". But there are two things to keep in mind.

First, not a good idea.

I know it seems to contradict what I answered to the other question, but what I said was that I personally try to have as few as% of% s in% as possible%.

Sometimes it is preferable to have a.h s in @class .

Returning to the example of the XPTO and YPTO classes. Imagine that all methods of the YPTO receive and / or return instances of XPTO. It is very likely that anyone who imports .h will also want to import #import , since YTPO has a dependency relationship with XPTO. In this case it will make sense that .h is in #import .

Second, you can not.

Although it seems so, there are situations where this is not possible.

@class Super
@interface Class : Super
    //...
@end

In this example, the compiler will not have a reference to the Super class and will not know how to resolve the inheritance.

As an extra, I want to warn you that if you want to do something like .h for protocols, you can do it with YPTO.h .

For example,

@protocol Delegate;
@interface Class : NSObject
    @proprety (weak, nonatomic) id<Delegate> delegate;
    //...
@end

However, it is not possible to do

@protocol Delegate;
@interface Class : NSObject <Delegate>
    //...
@end

because the compiler will not have the protocol reference.

    
12.05.2014 / 17:48
3
  

My question is: when to use @class or #import ?

  • @Class: This is used when we want to declare an object of any class.

    // File: CadastroAnimal.h

    @class Animal; @interface CadastroAnimal: UIViewController {     Animal * _animal; } @end

  • import: It is used when we want to use the methods of any class or we want to define the delegate for this class.

    // File: CadastroAnimal.h

    import Animal.h

    @interface CadastroAnimal: UIViewController {    Animal * _animal; }

  

I could delete the imports of all my classes that refer to other classes and simply write @class and then import them into the implementation file?

Doing this means that we do not want to use the methods of the "Animal" class at this point, nor do we want to define the class delegate "Animal.h" . Hence we can use this to increase the speed of the compiler.

If you use #import "Animal.h" and you do not want to define the class delegate, you should do the import only in the implementation file , since we will use your methods only in this file.

    
03.02.2014 / 16:00
1

In your header file, when you need to refer to a class you use @class, already inside your source you will use the class and not just reference it, then you use #import

    
10.02.2014 / 15:45