将程序拆分为多个小文件有助于更快地找到重要的代码,而且其他人在查看项目时也能有个大致的了解。

拆分接口和实现

根据@interface@implementation,OC的代码通常放在两种文件里:

  • 接口部分(.h):类的@interface指令、公共struct定义、enum常量、#defines和extern全局变量等。
  • 实现部分(.m): 类的@implementation指令、全局变量的定义、私有struct等。

另外,复杂的项目可以拥有多个目标,它们源文件的配置各不相同,构建规则也不同。群组关系仅仅是有Xcode负责管理的一项奇妙的功能。

拆分Car程序

  • #import 带尖号的是导入系统头文件(只读),如#import <Foundation/Foundation.h> ;双引号是项目本地的代码文件,如#import "Engine.h"
  • 拆分上一篇中的Car程序 首先拆分继承自NSObject的类:TireEngine
1
2
3
4
5
6
7
  //  Tire.h

  #import <Foundation/Foundation.h>

  @interface Tire : NSObject

  @end
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
  //  Tire.m

  #import "Tire.h"

  @implementation Tire
  //#pragma mark -
  - (NSString *)description {
      return (@"I am a Tire.");
  } //description

  @end
1
2
3
4
5
6
7
  //  Engine.h

  #import <Foundation/Foundation.h>

  @interface Engine : NSObject

  @end
1
2
3
4
5
6
7
8
  //  Engine.m
  #import "Engine.h"

  @implementation Engine
  - (NSString *)description {
      return (@"I am a Engine.");
  } //description
  @end

使用跨文件依赖关系

  • @class 是告诉编译器:“这是一个类,只会通过指针来引用它,不需要关注此类的更多信息”。可减少必须导入的头文件的数量,从而缩短编译时间。 拆分Car类:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
      //  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
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    
      //  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部分。 拆分Slant6AllWeatherRadial

    1
    2
    3
    4
    5
    6
    7
    
      //  Slant6.h
    
      #import "Engine.h"
    
      @interface Slant6 : Engine
    
      @end
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
      //  Slant6.m
    
      #import "Slant6.h"
    
      @implementation Slant6
      - (NSString *)description {
          return (@"I am a slant-6.VROOM!");
      }
      @end
    
    1
    2
    3
    4
    5
    6
    7
    
      //  AllWeatherRadial.h
    
      #import "Tire.h"
    
      @interface AllWeatherRadial : Tire
    
      @end
    
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
      //  AllWeatherRadial.m
    
      #import "AllWeatherRadial.h"
    
      @implementation AllWeatherRadial
      -(NSString *)description
      {
          return (@"I am a tire for rain or shine.");
      }
      @end
    

最后是main.m文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//  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;
}