import、#include和@class有什么区别
、相互引用头文件问题

2,175 阅读2分钟

import、#include和@class有什么区别

  1. #import是Objective-C导入头文件的关键字
    • import会包含这个类的所有信息,包括实体变量和方法
    • 使用#import头文件会自动只导入一次,不会重复导入,相当于#include和#pragma once
  2. #include是C/C++导入头文件的关键字
  3. @class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包含

    @class只是告诉编译器,其后面声明的名称是类的名称。

  4. #import<>用来导入系统的头文件,#import“”用来导入用户的头文件。

相互引用头文件问题

  • 如果有循环依赖关系,如:A–>B, B–>A这样的相互依赖关系。
    • 首先,两个.m文件互相引用.h文件,不会出现问题的。
    • 但是比如在.h里的某个属性,类型是自定义的类,这时候如果只在.m里引用就编不过了。
//  JTTest1.h
#import <Foundation/Foundation.h>
#import "JTTest2.h"

@interface JTTest1 : NSObject
@property (nonatomic, strong) JTTest2 *test; //!!报错“Unknown type name 'JTTest2'; did you mean 'JTTest1'?”

@end


//  JTTest2.h
#import <Foundation/Foundation.h>
#import "JTTest1.h"

@interface JTTest2 : NSObject

@end

  • 解决:
    使用@class。在.h文件中使用@class,然后在.m文件中#import "JTTest2.h"即可。
//  JTTest1.h
#import <Foundation/Foundation.h>
@class JTTest2;

@interface JTTest1 : NSObject
@property (nonatomic, strong) JTTest2 *test; 
@end


//  JTTest1.m
#import "JTTest1.h"
#import "JTTest2.h"
@implementation JTTest1

@end
  • 原因: @class JTTest2;这句话的意思就是,告诉编译器,确实有JTTest2这个类,具体细节你不用管,别报错就行了。所以显然,到了.m里,它只知道有这个类,却不知道这个类有什么属性,有哪些方法。所以需要在.mimport这个头文件。

尽量在.m而不是.h里使用import引用

所以我们推荐尽量在.m里引用头文件,而不是在.h里,必要时使用@class

在编译效率方面考虑,如果你有100个头文件都#import了同一个头文件,或者这些文件是依次引用的,如A–>B, B–>C, C–>D这样的引用关系。当最开始的那个头文件有变化的话,后面所有引用它的类都需要重新编译,如果你的类有很多的话,这将耗费大量的时间。而是用@class则不会。

但是也有一些情况,是不可避免要在.h里引用的。比如:继承某个类,必须在.himport 父类的.h;类实现某个接口,必须在.h里引用接口的.h等等。