将程序拆分为多个小文件有助于更快地找到重要的代码,而且其他人在查看项目时也能有个大致的了解。
拆分接口和实现
根据@interface
和@implementation
,OC的代码通常放在两种文件里:
- 接口部分(.h):类的@interface指令、公共struct定义、enum常量、#defines和extern全局变量等。
- 实现部分(.m): 类的@implementation指令、全局变量的定义、私有struct等。
另外,复杂的项目可以拥有多个目标,它们源文件的配置各不相同,构建规则也不同。群组关系仅仅是有Xcode负责管理的一项奇妙的功能。
拆分Car程序
#import
带尖号的是导入系统头文件(只读),如#import <Foundation/Foundation.h>
;双引号是项目本地的代码文件,如#import "Engine.h"
。-
拆分上一篇中的Car程序
首先拆分继承自NSObject
的类:Tire
和Engine
。// Tire.h #import <Foundation/Foundation.h> @interface Tire : NSObject @end
// Tire.m #import "Tire.h" @implementation Tire //#pragma mark - - (NSString *)description { return (@"I am a Tire."); } //description @end
// Engine.h #import <Foundation/Foundation.h> @interface Engine : NSObject @end
// Engine.m #import "Engine.h" @implementation Engine - (NSString *)description { return (@"I am a Engine."); } //description @end
使用跨文件依赖关系
-
@class
是告诉编译器:“这是一个类,只会通过指针来引用它,不需要关注此类的更多信息”。可减少必须导入的头文件的数量,从而缩短编译时间。
拆分Car
类:// Car.h #import <Foundation/Foundation.h> @class Engine; @class Tire; @interface Car : NSObject - (Engine *) engine; - (void) setEngine: (Engine *) newEngine; - (Tire *) tireAtIndex: (int) index; - (void) setTire: (Tire *) tire atIndex: (int) index; - (void)print; @end //Car
// Car.m #import "Car.h" #import "Tire.h" #import "Engine.h" @implementation Car { Engine *engine; Tire *tires[4]; } - (Engine *) engine { return (engine); } //engine - (void) setEngine:(Engine *)newEngine { engine = newEngine; } //setEngine - (void) setTire:(Tire *)tire atIndex:(int)index { if (index<0 || index>3) { NSLog(@"bad index (%d) in setTire:atIndex", index); exit(1); } tires[index] = tire; } // setTire - (Tire *) tireAtIndex:(int)index { if (index<0 || index>3) { NSLog(@"bad index (%d) in setTire:atIndex", index); exit(1); } return tires[index]; } // tireAtIndex - (id)init { if (self = [super init]) { //? engine = [Engine new]; tires[0] = [Tire new]; tires[1] = [Tire new]; tires[2] = [Tire new]; tires[3] = [Tire new]; } return (self); } - (void)print { NSLog(@"%@", engine); NSLog(@"%@", tires[0]); NSLog(@"%@", tires[1]); NSLog(@"%@", tires[2]); NSLog(@"%@", tires[3]); } @end //Car
-
编译器需要先知道所有关于超类的信息才能成功地为其子类编译@interface部分。
拆分Slant6
和AllWeatherRadial
:// Slant6.h #import "Engine.h" @interface Slant6 : Engine @end
// Slant6.m #import "Slant6.h" @implementation Slant6 - (NSString *)description { return (@"I am a slant-6.VROOM!"); } @end
// AllWeatherRadial.h #import "Tire.h" @interface AllWeatherRadial : Tire @end
// AllWeatherRadial.m #import "AllWeatherRadial.h" @implementation AllWeatherRadial -(NSString *)description { return (@"I am a tire for rain or shine."); } @end
最后是main.m
文件:
// main.m
#import <Foundation/Foundation.h>
#import "Car.h"
#import "Tire.h"
#import "Engine.h"
#import "Slant6.h"
#import "AllWeatherRadial.h"
int main(int argc, const char * argv[]) {
Car *car = [Car new];
Engine *engine = [Slant6 new];
[car setEngine:engine];
for (int i=0; i<4; i++) {
Tire *tire = [AllWeatherRadial new];
[car setTire:tire atIndex:i];
}
[car print];
return 0;
}