第一章熟悉Objective-C
第1条:了解Objective-C语言起源
消息与函数的区别:使用消息结构的语言,其运行时所应执行的代码由运行环境来决定; 使用函数调用的语言,由编译器决定
- 对象所占内存总是分配在
堆空间(heap space)
,绝不会分配在栈(stack)
上 - 分配在堆中的内存必须直接管理,分配在栈上用于保存变量的内存会在栈帧弹出时自动清理
要点:
- Objective-C使用动态绑定的消息结构,在运行时检查对象类型。接收到一条消息后,应执行何种代码,由运行期环境而非编译器决定。
第2条: 在类的头文件中尽量少引入其他头文件
- 用Objective-C编写‘类’(class)的标准方式为:以类名做文件名,分别创建两个文件,头文件后缀用
.h
,实现文件后缀用.m
- 将引入头文件的时机尽量延后,只在确有需要时才引入,这样可以减少类的使用者所需引入的头文件数量
- @class xxx;
向前声明
(forward declaring):编译时不需要知道xxx
类的全部细节,只需知道有一个叫xxx
的类名就好。
要点:
- 除非却有必要,否则不要引入头文件。一般来说,应在某个类的头文件中使用向前声明来提及别的类,并在实现文件中引入那些类的头文件。这样做可以尽量降低类之间的耦合(couping).
- 无法使用向前声明时,比如要声明某个类遵循一个协议。这种情况下尽量把“该类遵循某协议”的这条声明移至
class-continuation分类
中。如果不行,就把协议单独放在一个头文件中,然后将其引入。
第3条:多用字面量语法,少用与之等价的方法
1
字面量语法(literal syntax)可以缩短源代码长度,更为易读 * 字面数值 `NSNumber` `@n`
@1,@2.5f,@3.14159,@YES,@’a’
- 字面量数组
@[]
若数组元素对象中有nil
,则会抛出异常 - 字面量字典
@{}
字典中的对象和键必须都是Objective-C对象;值出现nil
,则会抛出异常 - 可变数组与字典:如果数组与对象是可变的(mutable),那么可以通过下标修改其中的元素值
- 局限性:出来字符串外,所创建出来的对象必须属于
Foundation
框架 - 使用字面量语法创建出来的字符串、数组、字典对象都是不可变的(immutalbe),若需要可变版本的对象,则需复制一份(mutableCopy)
要点:
- 应该使用字面量语法来创建字符串、数值、数组、字典。
- 应该通过取下标操作访问数组下标或字典中键对应的元素。
- 用字面量语法创建数组或字典时,若值中有
nil
,则会抛出异常。
第4条:多用类型常量,少用#define预处理指令
1
2
#define: 不含常量类型,多文件使用时被统一替换,容易遭人修改
类型常量: 包含类型信息,命名信息明确,编译器确保值不变 * 常用的命名法:若常量局限于某实现文件之内,则在前面加字母`k`;若常量在类之外可见,则通常以类名为前缀 * 常量的定义位置:若不公开,定义在使用该常量的实现文件里。若公开,名称加前缀,放头文件 * 常量定义从右向左解读 * 变量声明:一定要同时用 `static` 与 ` const`,如果试图修改由 `const`修饰符声明的变量,编译器报错;`static`修饰符意味着该变量仅在定义此变量的编译单元(每个类的实现文件)中可见,若不加`static`,则编译器默认创建`外部符号(external symbol)`,此时若其他单元出现同名变量,编译器抛出异常;同时static与const,编译器不在创建符号,像#define一样,替换变量为常值 * 对外公开的常量:`extern` 此关键字告诉编译器,此常量在全局符号表中,编译器无需查看其定义,即允许代码使用。在头文件声明,在实现文件定义 * 对外公开常量的位置:必须定义,且一次。放在与声明该常量的头文件相关的实现文件里。
要点:
- 不要用预处理指令定义常量。1.定义的常量不含类型信息,编译器只会在编译前执行查找替换。若重新定义,编译器无警告,导致应用中常量值不一致。
- 在实现文件中使用static const定义 “只在编译单元中可见的常量”,不在全局符号表中,无需前缀
- 在头文件中使用extern来声明全局常量,在相关实现文件中定义其值,名称用与之相关的类名做前缀
第5条:用枚举表示状态、选项、状态码
1
枚举只是一种常量命名方式 * 编译器会为枚举分配一个独有的编号,从0开始,每个枚举递增1. * 实现枚举所用的数据类型取决于编译器,不过其二进制位(bit)的个数必须能完全表示下枚举编号。 * 选项的枚举值经常使用按位或`|`运算符组合 * 两种宏定义方法:若枚举不需要相互组合使用`NS_ENUM`定义,需要按位或组合的枚举使用 `NS_OPTIONS`定义
要点:
- 应该用枚举来表示状态机的状态、传递给方法的选项以及状态码等值,给这些值起易懂的名字
- 如果把传递给某个方法的选项表示为枚举类型,而多个选项又可同时使用,那么就将各项定义为2的幂,以便通过按位或将其组合起来
- 使用NS_ENUM与NS_OPTIONS宏来定义枚举类型,并指明其底层数据类型。这样做可确保枚举是用开发者所选的底层数据类型实现出来的,而不是采用编译器所选的类型。
- 在处理枚举类型的switch语句中不要实现default分支。这样,加入新枚举分支之后编译器会提示开发者(警告):switch语句并未处理所有枚举