2.1 代码文件
第1章,我们已经看到了一个简单Objective-C程序是如何跑起来的。下面,我们来看一看几种常见的代码文件。
首先请.h文件出场,谁让它是头(header,如果你喜欢,可以加儿音)文件呢。那么,头文件的功能是什么呢?和C/C++相似,在Objective-C中,头文件的作用就是声明一系列可供其他文件使用的资源,如函数、全局变量、类的接口部分等。请注意,在头文件里只负责声明,就当是Mark一下,刷一下存在感,而不是资源真正的定义和实现,那么,这些工作都是在哪里完成的呢?马上请出第二位。
有请.m文件出场,这是模块(module)文件。是的,真正的定义和实现一般都会放在.m文件中,如前面提到的函数的定义、全局变量的定义、类的实现部分等内容。稍后,我们会看到.h和.m文件是如何配合使用的。
深呼吸,下面继续!
.c文件,C语言代码文件,它的角色与.m的角色相似,经常需要与头文件一起使用。当我们开发iOS或OS X系统下的应用时,会用到很多C语言实现的资源,这些资源定义在一个总称为Core Foundation的框架中,比如,在图形处理时,我们会用到Core Graphics框架中的资源。
.cpp文件,C++源代码文件。是的,我们同样可以编写C plus plus代码,听说它也是面向对象的。
.swift文件,这只鸟看着挺眼熟,就是Swift源代码文件了。Swift是另一种来自苹果公司的编程语言。此外,听说一只小Swift正在四处漂泊,也许作者会带着大家了解它的故事,一起期待吧!
现在,打开Xcode,我们继续使用第1章创建的SimpleOC项目,当然,也可以新建一个OS X系统下的“Command Line Tool”类型项目。
接下来,在项目中,通过Xcode菜单“File”→“New”→“File”项创建一个头文件(Header File),并命名为CApp.h,如图2-1所示。
图2-1 创建头文件
接下来,我们修改这个文件的内容,首先,可以把绿色内容删除,也可以修改为其他内容,哪个星球的语言就不重要了,只是要记得使用//作为行的开头,而且习惯上还会加一个空格。下面的代码就是我修改后的CApp.h文件。
#ifndef __CApp_h__ #define __CApp_h__ extern int gDeviceType; void deviceInit(); #endif
这么多#符号是什么情况?我们说过,它们称为预处理指令。
预处理,就是预先处理?是的,只不过这些工作由编译器来完成,我们只要正确书写就行了。那怎么正确书写呢?这个也不难,基本的要求就是:#符号别忘了,字母拼对了,最后就不要加分号了!真的很简单,对吧。
接下来,我们先从字面上了解这些指令的功能。
#ifndef和#endif指令的功能是,如果没有定义“__CApp_h__”宏(使用#define指令定义,稍后说明),则执行#ifndef和#endif指令之间的内容。默认情况下,Xcode中会自动使用“项目名称+头文件名”的格式来定义宏,我们可以使用默认的宏名称,也可以根据项目约定进行相应的修改。
#define指令用于定义宏,这是货真价实的符号,而且,在定义宏的同时也可以定义它表示的值,如:
#define DT_IPAD 1000
本例中,编译器开工时,会在代码中使用1000替换所有DT_IPAD标识,而这也是宏的基本功能之一。在后续的内容中,我们会看到更多关于宏的应用。
再来看两个声明语句(都说了头文件中只是声明了):
extern int gDeviceType; void deviceInit();
第一条语句声明了一个整数类型(int)的变量gDeviceType,其中extern关键字说明此变量是定义在另外的文件中的,第二条语句声明了一个函数deviceInit()。请注意,它们都以分号作为结束,这是基本的语句形式,请大家区分语句和预处理指令。此外,我不会告诉你它们是定义在CApp.m文件里的。
接下来,通过Xcode菜单“File”→“New”→“File”,创建一个Objective-C文件(Objectie-C File),并命名为CApp.m,如图2-2所示。
图2-2 创建模块文件
然后,修改CApp.m文件的内容如下面的代码。
#import "CApp.h" int gDeviceType; void deviceInit() { NSLog(@"项目初始化工作..."); gDeviceType = DT_IPAD; }
最后,我们在main()函数中(main.m文件)使用它们,如下面的代码。
#import <Foundation/Foundation.h> #import "CApp.h" int main(int argc, const char *argv[]) { @autoreleasepool { deviceInit(); NSLog(@"%i", gDeviceType); } return 0; }
执行代码,显示结果如图2-3所示。
图2-3 头文件与模块文件应用测试结果
通过这部分的练习,我们应该了解.h和.m文件是如何配合使用的,为进一步的开发工作做好准备。
此外,当我们需要使用某个头文件的资源时,不要忘了使用#import指令引用它,对于我们自己创建的头文件,使用一对双引号来引用,如下面的代码。
#import "CApp.h"