OC是一种消息型语言,使用的是“消息结构”而非“函数调用”,由smalltalk演化而来。使用消息结构的语言运行时执行的代码由运行环境来决定,而使用函数调用的语言由编译器决定。
OC将堆内存管理抽象出来了。不需要使用malloc或者free来分配或释放对象所占的内存。OC运行期环境把这部分工作抽象成一套内存管理架构,名为“引用计数”。
当编译一个A类的文件时,想要引入B类,但是不需要知道B类的全部细节,只需要知道有一个类叫B类,可以使用:
@class B;
但是如果要在A类的实现文件中使用B,则需要使用import声明,因为要使用它就要知道B类的所有细节。
这样做延后了引入头文件的时机,只有在确有需要时才引入,这样就可以减少类的使用者所需引入的头文件数量,减少编译时间。
向前声明同样可以解决两个类互相引用的问题。在两个类中互相引用对方的头文件,就会造成“循环引用”。当解析一个头文件时,会发现它引用了另一个头文件,而那个头文件又回头引用了第一个头文件。使用#import而非#include虽然不会导致死循环,但是会使得两个类中有一个无法被正常编译。
如果你写的类继承自某个超类,则必须引入定义那个超类的头文件,同理如果要声明你写的类遵从某个协议,那么该协议必须有完整定义,且不能向前声明。因为向前声明只是声明某个协议的存在,而此时编译器却需要知道该协议的具体定义。
使用字面量语法可以缩减代码长度,使其更为易读。
NSString:
NSString *str = @“...”;
NSNumber:
NSNumber *num = @1;
NSArray:
NSArray *arr = @[@“1”, @“2”, @“3”];
NSString *two = arr[1];
NSDIctionary:
NSDictionary *dict = @{@“1”: @“one”, @“2”: @“two”, @“3”: @“three”};
NSString *two = dict[@“2”];
NSMutableDictionary和NSMutableArray:
//字面量语法修改可变数组或者字典中的元素时可这样修改
mutableArray[1] = @“2”;
mutableDictionary[@“3”] = @“4”;
在数组中使用字面量语法时,倘若我们放入数组的元素是变量,其中一个变量为nil,那么编译器会报出异常,方便我们及时发现问题。但是如果使用的不是字面量语法,比如NSArray *arr = [NSArray arrayWithObjects: obj1, obj2, obj3, nil]; 在这个数组中如果obj2为nil,那么arr的值就会只有obj1,它不会报出异常,这是因为arrayWithObjects方法处理参数时发现nil就停止了,这也导致我们无法及时发现问题。字典同理。
因此,使用字面量语法也有助于我们快速发现问题。
字面量语法有个限制就是:除了字符串以外,所创建的对象必须属于Foundation框架才行。意思是自定义的这些类的子类是不能用字面量语法的。
使用字面量语法创建出来的字符串、数组、字典对象都是不可变的。若想要可变版本,需要:
NSMutableArray *mutableArray = [@[@1, @2, @3, @4]mutableCopy];
定义常量应用static const,这样方式定义的常量包含类型信息,可以清楚的了解常量的含义。
定义的常量不应该放在头文件里。如果不打算公开某个常量,则应该将其定义在实现文件里。
变量一定要同时用static和const声明,如果试图修改由const修饰符所声明的变量,那么编译器就会报错。
有时候需要对外公开某个常量,比如使用通知传值的时候要用一个对象来派发通知,然后让其他接收通知的对象来注册通知完成传值。在派发通知的时候需要使用一个字符串来表明这个通知的名称,这个名称就可以声明为一个外界可见的常值变量。这样注册者就无需知道实际字符串的值,只需要以常值变量来注册自己想要接收的通知就行。这一类常量应该放在“全局符号表”中,以便可以在定义该常量的编译单元之外使用。
定义在全局符号表中:
extern NSString *const stringConst;
NSString *const stringConst = @“value”;
//在上面的代码中,stringConst是一个指针常量,指向NSString对象。
在以一系列常量来表示错误状态码或可组合选项时,宜用枚举为其命名。
定义枚举的语法:
enum connectionState state = disconnected;
enum connectionState {
disconnected,
connected,
connecting,
};
typedef enum connectionState connectionState;
connectionState state = disconnected;
可以指明用何种“底层数据类型”来保存枚举值的变量。因此这样做就可以向前声明枚举变量。若不指明底层数据类型就不可以向前声明,因为编译器不清楚底层数据类型的大小,不知道要给它分配多少空间。
指定底层数据类型:
enum connectionState: NSInteger{...};
在向前声明时指定底层数据类型:
enum connectionState: NSInteger;
不使用编译器分配的序号,使用自定义指定的值:
enum connetcionState {
//将disconnected的值设为1,而不是编译器指定的0,这样接下来几个枚举的值都会是上一个的值+1
disconnected = 1,
connected,
connecting,
};
定义选项时可以通过枚举组合选项,各选项之间通过“按位或操作符”来组合。