源文件组织
1.1 拆分接口和实现
主要讨论把程序代码拆分到不同文件中的方法。
Objective-C的源代码分为两部分。一部分是接口,用来展示类的构造。接口包含了使用该类所需的所有信息。编译器将@interface部分编译后,你才能使用该类的对象,调用类方法,将对象复合到其他类中,以及创建子类。源代码的另一个组成部分是实现。@implementation部分告诉Objective-C编译器如何让该类工作。这部分代码实现了接口所声明的方法。
在类的定义中,代码很自然地被拆分为接口和实现两个部分,所以类的代码通常分别放在两个文件里。一个文件存放接口部分的代码:类的@interface指令、公共struct定义、enum常量、#defines和extern全局变量等。由于Objective-C继承了C的特点,所以上述代码通常放在头文件中。头文件名称与类名相同,只是用.h做后缀。所有的实现内容(如类的@implementation指令、全局变量的定义、私有struct等)都被放在了与类同名但以.m为后缀的文件中(有时叫做.m文件)。类的使用者可以通过#import命令导入头文件来获得该类的功能。
如果用.mm做文件扩展名,编译器就会认为你是用Objective-C++编写的代码,这样你就可以同时使用C++和Objective-C来编程了。
目标(Target), 复杂的项目可以拥有多个目标,它们源文件的配置各不相同,构建规则也不同。
Xcode中有一个与项目同名的群组,文件都放在群组内的文件夹中。(你可以在项目导航器中浏览项目文件的构造。) 这些文件夹(在Xcode中称作群组)能够帮你组织项目中的源文件。你可以创建存放用户界面类的群组,也可以创建存放数据处理类的群组,这样项目更易于浏览。在设置群组时,Xcode并不会在硬盘上移动文件或者创建目录。群组关系仅仅是由Xcode负责管理的一项奇妙的功能。可以设置Xcode中的群组指向文件系统中某个特定的目录,Xcode会帮你将新建的文件放入该目录中。
1.2 拆分程序
在.m文件中一般引入.h文件的头文件,原因是:编译器需要知道类里的实例变量配置,这样才能生成合适的代码,但是它并不知道与源文件配套的头文件也存在。所以,需要在.m文件中引入.h文件的头文件,将此信息告知编译器。在程序编译时,如果你碰到了“Can not find interface declaration for Tire”(无法找到Tire类的接口定义)之类的错误信息,通常是因为你忘记用#import导入类的头文件了。
注意:导入头文件有两种方法:使用引号或者尖括号。带尖括号的语句用于导入系统头文件,而带引号的语句则说明导入的是项目本地的头文件。
1.3 使用跨文件依赖关系
依赖关系(dependency)是两个实体之间的一种关系。在编程和开发中,经常会出现关于依赖关系的问题。依赖关系可以存在于两个类之间。依赖关系也可以存在于两个或多个文件之间。导入头文件使头文件和源文件之间建立了一种紧密的依赖关系。如果头文件有任何变化,那么所有依赖它的文件都得重新编译。这会在需要编译的文件中引发一连串的变化。尽管重新编译需要花费很长的时间,但至少Xcode帮你记录了所有的依赖关系。
1.3.1 重新编译须知
导致依赖关系问题的原因是Objective-C编译器需要某些信息才能够工作。有时候编译器需要知道类的全部信息,而有的时候,编译器只需要知道类名即可,不需要了解整个定义。
复合通过指针指向对象,这之所以能行得通,是因为所有Objective-C对象都使用动态分配的内存。
Objective-C引入了关键字@class来告诉编译器:“这是一个类,所以我只会通过指针来引用它。” 这样编译器就放心了:它不必知道关于这个类的更多信息,只要了解它是通过指针来引用的即可。@class创建了一个前向引用。如果有循环关系,@class也很有用。即A类使用B类, B类也使用A类。如果试图通过#import语句让两个类相互引用,那么就会出现编译错误。但是如果在A.h文件中使用@class B, 在B.h文件中使用@classB, 那么这两个类就可以相互引用了。
如果A类继承自B类,则需要在.h文件中导入B类的头文件,而不能用@class。(因为这里是继承自其他类而不是指向其他类的)因为编译器需要先知道所有关于超类的信息才能成功地为其子类编译@interface部分。它需要了解超类中实例变量的配置信息(数据类型、大小和排序)。在子类添加实例变量时,它们会被附加在超类实例变量的后面。然后编译器就利用这些信息计算在内存的什么位置能找到这些实例变量,每个方法都通过自身的self隐藏指针进行寻找。为了能够精确地计算出实例变量的位置,编译器必须先了解该类的所有内容。
注意,文件导入过于混乱会延长编译时间,也会导致不必要的重复编译。而巧妙使用@class指令,可以减少必须导入的头文件的数量,从而可以缩短编译时间。
“pragma”源自希腊语,意思是“行动”。#pragma指令将Objective-C常规代码之外的信息或说明传递给编译器和代码编辑器。通常,pragma是被忽略的,但它在一些软件开发工具中可能有其他的含义。如果某个工具并不知道pragma是什么,并不会生成警告或错误信息,而是很聪明地忽略它。
Xcode中有两种调试器可供选择:GDB和LLDB。GDB是GNU计划的一部分,可以在各种平台上兼容。LLDB是LLVM计划多个Xcode工具中的一员。目前两者之间的不同主要是精细度和内联性。
《Objective-C基础教程》读书笔记4—OC扩展
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 1108 朱海燕 Jody 每次翻开书,看到这些活泼可爱又调皮捣蛋的小猴子,我三个女儿都超级喜欢,相信只要看过这本...
- 文章很短,因为只是三个简单的认知,但绝对让你有可能焕然一新 1、建立自信从叠被子开始 小时候,我家里很穷,我爸妈都...