决定用一个读书笔记作为自己掘金博客的第一篇会比较好,压力也比较小。最近在读《编写高质量iOS与OS X代码的52个有效方法》,觉得应该记下来的细小的点非常多,希望大家看了我的读书笔记也能有所裨益吧。
如何减少头文件的引入
有时候在OC的头文件声明一些属性或者方法,此时可能会依赖一些其他的类,常规的做法是直接引入依赖类的头文件。比如:
#import <Foundation/Foundation.h>
#import "Head.h"
@interface APerson:NSObject
@property(nonatomic,strong)Head *personHead;
@end
这里,由于APerson
需要声明一个Head类型的属性,于是引入了Head.h
,这么做有一个问题,如果APerson
声明中并不需要Head
这个类的所有细节,比如上面例子所示,仅仅只是想要声明personHead的类型是Head
。此时,如果仅仅只是Head.h
文件进行了改动,那么APerson
和其他引入Head.h
的文件都要重新进行编译,对于大型项目来说,编译的效率会变得非常低下。
那么该如何优雅的解决这个问题呢?
可以通过@class
关键字告诉编译器,当前依赖的Head
类我并不需要所有的细节,我只要知道有一个类的名字叫做Head
就可以,所以上述代码就变成了这样:
#import <Foundation/Foundation.h>
@class Head;
@interface APerson:NSObject
@property(nonatomic,strong)Head *personHead;
@end
这叫做向前声明(forward declaring)
该类,向前声明后,在实现文件(APerson.m
)中引入需要的头文件即可,也就是在需要使用Head
类时,获取这个类的具体接口细节。这样就可以把引入头文件的时机延迟到明确需要的时候,提高编译效率。
更多的时候,@class
可以完美的解决两个类头文件相互引入的问题,避免编译错误。
在理解以上概念之后,其实就可以区分什么场景该用#import
,什么场景该用@class
。很关键的一点就是是否需要知道依赖类的接口细节。下面有两点就是典型的不能使用@class
的场景:
- 子类继承父类后,需要引入父类的头文件,此时只能使用
#import
。因为在编译时,子类的头文件需要知道父类的接口细节才能完成继承。 - 当前类用到了依赖的类的接口,涉及到了依赖类的属性和方法,此时也必须要用
#import