前言
最近买了一本Effecitve Objective-C 2.0来看,写的比较详细,决定边看边记录变分享。
头文件的导入
在Objective-C中,我们使用#import来导入另一个类的头文件。
但在编译阶段,频繁的#import 会增加编译器的编译时间。
当然可以说现在硬件设备都很好,固态硬盘速度快,随便#import不会增加多少时间的。
我觉得不管如何,高效编写代码,无论从哪个地方着手,去计较,都是不为过的。
情况一
下面说个例子:
#import <Foundation/Foundation.h>
#import "Teacher.h"
@interface HightSchoolClass : NSObject
@property (nonatomic, strong) NSString *className;
@property (nonatomic, assign) NSInteger studentsCount;
@property (nonatomic, strong) Teacher *teacher;
@end
你有一个HightSchoolClass类,还有一个Teacher类,每一个HighSchoolClass类中都有一个teacher对象,这种情况下你完全可以使用#import "Teacher.h" 来告诉HighSchoolClass去导入Teacher类。
但是这种简单的情况下,我们没有必要让HightSchoolClass类去知道Teacher类的一些详细信息,我们只需要告诉编译器,有一个类叫Teacher就行了
因此用@class teacher;是一种更加高效的方法,如下:
#import <Foundation/Foundation.h>
@class Teacher;
@interface HightSchoolClass : NSObject
@property (nonatomic, strong) NSString *className;
@property (nonatomic, assign) NSInteger studentsCount;
@property (nonatomic, strong) Teacher *teacher;
@end
这样做的好处在于节省了一次导入,也同时避免了#import HighSchool 类的另一个类也会跟着导入没有必要导入的Teacher类。
情况二:
先有鸡还是先有蛋?
在Teacher.h中我们添加一个joinClass:方法,如下:
#import <Foundation/Foundation.h>
#import "HightSchoolClass.h"
//@class HightSchoolClass;
@interface Teacher : NSObject
@property (nonatomic, strong) NSString *name;
- (void)joinClass:(HightSchoolClass *)newClass;
@end
同时在HighSchoolClass中我们也添加一个方法addTeacher:方法,如下:
#import <Foundation/Foundation.h>
#import "Teacher.h"
@interface HightSchoolClass : NSObject
@property (nonatomic, strong) NSString *className;
@property (nonatomic, assign) NSInteger studentsCount;
@property (nonatomic, strong) Teacher *teacher;
- (void)addTeacher:(Teacher *)newTeacher;
@end
注意两个类的头文件都互相#import了对方,造成了先有鸡还是先有蛋的问题。
此时@class 就能完美解决这个问题。
情况三:
导入一个含有协议的大型类。
有些时候,我们希望自己写的一个类去遵守某个协议,比如HighSchoolClass 有一个@Protocol 叫 Patrol,旨在班级晚休时有人进行巡逻查看,巡逻的人是保安也好,老师也好,学生干部自己也好,不重要,只要遵守Patrol协议的人都能巡逻。
所以我们让HighSchoolClass声明一个协议:
#import <Foundation/Foundation.h>
#import "Teacher.h"
@protocol Partrol<NSObject>
- (void)partrol;
@end
@interface HightSchoolClass : NSObject
@property (nonatomic, strong) NSString *className;
@property (nonatomic, assign) NSInteger studentsCount;
@property (nonatomic, strong) Teacher *teacher;
- (void)addTeacher:(Teacher *)newTeacher;
@end
然后新建一个叫Security的保安类,
.h下:
#import <Foundation/Foundation.h>
#import "HightSchoolClass.h"
@interface Security : NSObject<Partrol>
@end
.m下实现patrol方法:
#import "Security.h"
@implementation Security
- (void)partrol
{
NSLog(@"我在巡逻");
}
@end
平时的时候, 之前我都是这么去实现的,要遵守某个协议,先#import声明了这个协议的类,比如这里就必须#import HighSchoolClass。
但是打个比方说,我作为巡逻的保安,我其实没那么必要去了解你那个班级有哪些学生,班主任是谁,班长是谁等等(举个例子而已)。
所以我们完全的#import HighSchoolClass就显得有些多余。
一个比较合适的解决方法就是把协议单独放在一个头文件中,或者单独写一个扩展 :
#ifndef Protocol_h
#define Protocol_h
@protocol Partrol<NSObject>
- (void)partrol;
@end
#endif /* Protocol_h */
因此在Security中只需要#import “Protocol.h”即可,而不需要import整个HightSchoolClass。这样可以减少依赖性。
但是还有一种情况是代理委托协议,也就是最常见的情况。这种情况下还是不要采用以上方式,因为协议只有与委托类放在一起才有意义。
小结
- 1 每次Import之前仔细想一想为什么要Import ,我是否要引入整个别的类而或我只是需要让编译器知道有这个类
- 2 遵循协议写类时,降低耦合,将协议单独书写出去。