import、#include和@class有什么区别
- #import是Objective-C导入头文件的关键字
- import会包含这个类的所有信息,包括
实体变量和方法
- 使用#import头文件会自动只导入一次,不会重复导入,相当于#include和#pragma once
- import会包含这个类的所有信息,包括
- #include是C/C++导入头文件的关键字
- @class告诉编译器某个类的声明,当执行时,才去查看类的实现文件,可以解决头文件的相互包含
@class只是
告诉
编译器,其后面声明的名称是类的名称。 - #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
里,它只知道有这个类,却不知道这个类有什么属性,有哪些方法。所以需要在.m
再import
这个头文件。
尽量在.m
而不是.h
里使用import
引用
所以我们推荐尽量在.m
里引用头文件,而不是在.h
里,必要时使用@class
。
在编译效率方面考虑,如果你有100个头文件都#import了同一个头文件,或者这些文件是依次引用的,如A–>B, B–>C, C–>D这样的引用关系。当最开始的那个头文件有变化的话,后面所有引用它的类都需要重新编译,如果你的类有很多的话,这将耗费大量的时间。而是用@class则不会。
但是也有一些情况,是不可避免要在.h
里引用的。比如:继承某个类,必须在.h
里 import 父类的.h
;类实现某个接口,必须在.h里引用接口的.h
等等。