Composition: use @class or #import?

Asked

Viewed 208 times

5

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

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

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

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 need to research to deepen the issue. I just want to give you a simple idea, I advise you to dig deeper.

But first, I’m gonna assume you don’t know C and give a brief explanation of how the code is turned into app.

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

1) Pre-compilation

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

It’s also this step that generates macro reset, for example, if we have the files a.h

#define MyDef 3

and b.h

#define MyDef 4

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

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

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

2) Compilation

This is the gist of the whole process, which is why it is also called compilation to the three steps together, because this is the main.

It is this step that transforms code into machine language. This step results in binary files as executable code. Has the bytes that the processor will interpret while running to know what to do.

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

3) Linking

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

This is also where resources are added to the final binary.


When using the directive @class we are telling the compiler that the class exists and that there is no need to verify its existence by delegating this verification to the linking.

For example:

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

This .h tell the compiler not to worry about XPTO that will be handled on linking.

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

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

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

What happens is that the compiler (and also the compiler) runs through the YPTO.m will i) read the YPTO.h, ii) read the XPTO.h and ii) read the @implementation YPTO.


When to use @class or #import?

Uses the @class when you don’t need the #import.

Personally, I try to have the minimum of #imports us .h possible. Using the example of the XPTO and YPTO classes. Imagine that later we created a ZPTO class that uses YPTO but does not need FOO. By doing the #import "YPTO.h", compiler will not waste time reading the XPTO,h nor the #imports his.

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

a. h

#import "b.h"

b. h

#import "a.h"

Where when reading the a.h, the compiler would read the b.h, which in turn would make the compiler read the a.h, b.h, a.h, ad infinitum.


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

I’m going to assume that when you say delete from the classes you mean .h.

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

First of all, it’s 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 the minimum of #imports us .h possible.

Sometimes it’s better to have #imports in the .h.

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

Second of all, you can’t.

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 solve the inheritance.


As an extra, I want to warn you that if you want to do something similar to @class for protocols, you can do it with the @protocol.

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.

3

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

  • @Class: Used when we want to declare an object of any class.

    // File: Animal register. h

    @class Animal; @interface Animal register : Uiviewcontroller { animal? _animal; } @end

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

    //File: Animal register. h

    import animal. h

    @interface Animal Register : Uiviewcontroller { Animal? _animal; }


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

Doing this means that we do not want to use the "Animal" class methods at this time, nor do we want to define the class delegate "Animal.h". So we can use this to speed up the compiler.

If you use the #import "Animal.h" and is not defining the delegate of the class it is better to make the import only in the implementation file, since we will only use your methods in this file.

1

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

Browser other questions tagged

You are not signed in. Login or sign up in order to post.