在使用 Objective-C 开发过程中,在一个头文件里面引入另一个头文件是一件正常不过的事情,不过这里面也有一些小技巧所在。
有一个 Person 类,这个类导入了 Employer 的头文件
// Person.h
#import <Foundation/Foundation.h>
#import "Employer.h"
@interface Person : NSObject
@property (nonatomic,copy) NSString *firstName;
@property (nonatomic,copy) NSString *lastName;
@property (nonatomic,copy) Employer *employer;
@end
同时 Employer 类导入了 Person 类的头文件
// Employer.h
#import <Foundation/Foundation.h>
#import "Person.h"
@interface Employer : NSObject
@property (nonatomic,copy) NSString *company;
@property (nonatomic,copy) NSString *number;
-(void)addEmployee:(Person *)person;
-(void)removeEmployee:(Person *)person;
@end
你觉得这个时候会发生什么情况呢?在各自头文件中引入了对方的头文件,这个情况下会导致头文件的循环引用,编译器报错。
如果是你,你会怎么解决这种头文件互相引用的问题呢?除了尽量避免头文件互相引用的情况发生之外,Objective-C 也给我们提供了一个 @class 向前声明的解决方案
#import <Foundation/Foundation.h>
@class Person;
@interface Employer : NSObject
@property (nonatomic,copy) NSString *company;
@property (nonatomic,copy) NSString *number;
-(void)addEmployee:(Person *)person;
-(void)removeEmployee:(Person *)person;
@end
@class Person; 的意思是告诉编译器现在你不用关心这个类的细节,你只需要知道有这么一个叫做 Person 的类就可以了。
使用了 @class Person; 之后,编译器就不会报错了。
在某些情况下这个 @class 向前声明也会有一些问题。在代码重构或者优化过程中,我将 Person 类的名字修改成 People 。
#import <Foundation/Foundation.h>
#import "Employer.h"
@interface People : NSObject
@property (nonatomic,copy) NSString *firstName;
@property (nonatomic,copy) NSString *lastName;
@property (nonatomic,copy) Employer *employer;
@end
这个时候项目的代码中已经不存在一个叫做 Person 的类了,但是编译器没有报错。这个可以算是 @class 的一个坑。当然你也可以在重构代码或者优化过程中先对重命名的类进行搜索,找到 Person 被引用的代码片段,然后将代码片段的 Person 修改为 People 。
总结
1、尽量不要在头文件中引入其他头文件,尽量在实现文件也就是 .m 文件中去引入头文件
2、在头文件中引入其他的类尽量使用 @class 向前声明的方式
3、引入头文件尽量使用 #import 而不是 #include , 因为 #import 可以避免重复引入同一个头文件
4、头文件引入的问题只是会影响编译器的编译时间,关于时间,我们还是能省则省。