iOS 编写高质量Objective-C代码(一)

Effective Objective-C 2.0 编写高质量iOS与OS X代码的52个有效方法

前言:
这几篇文章是《Effective Objective-C 2.0》的知识产出,做下笔记拓展自己的知识层面。

iOS 编写高质量Objective-C代码(一)

1.第一章:熟悉Objective-C

第1条:了解Objective-C语言的起源

OC由语言Smalltalk演化而来, Smalltalk消息传递型语言的鼻祖。

消息传递

OCC++Java等面向对象语言类似,不过很多方面有所差别,因为OC使用 “消息传递”机制 而C++Java使用“函数调用”机制

// Objective-C : messaging (消息传递)
Object *obj = [Object new];
[obj performWith:parameter1 and:parameter2];

// C++: function calling(函数调用)
Object *obj = new Object;
obj->perform(parameter1, parameter2);

区别:
消息传递:运行时所执行的代码由运行时环境决定(runtime)
函数调用:运行时所执行的代码由编译器决定

简单来说,OC总在运行时才会去查找真正所要调用的方法,编译器并不用关心接收消息的对象是什么类型,接收消息的对象也是在运行时才工作,其过程叫做动态绑定(dynamic binding)。而其他大部分面向对象语言,会在运行时查找“虚方法表”(virtual table)来查出执行的方法(是调用子类的方法?还是父类的方法?)。

指针

OCC语言的“超集”,在 C语言的基础上添加了面向对象的特性。C语言里的大部分知识在编写OC代码时依然适用。

OC里的指针主要用来指示对象,基本语法和C语言类似。

  • 例如:声明一个字符串
    NSString *someString = @"The String";
    NSString *anotherString = someString;

语法解释:声明了一个名为someString的变量,其类型为NSString *。是一个指向NSString的指针。

  • 错误案例:
    NSString str;

报错:error:interface type cannot be statically allocated
解释:对象不允许声明在栈空间上

不能在栈中分配OC对象,因为OC对象所占的内存会被分配在堆空间(heap space)上,由程序员来控制它的内存分配。而栈空间的临时基本数据由编译器控制

  • 再举一个典型案例:
    xxxClass *Qi = [[xxxClass alloc] init];
    xxxClass *Share = Qi;

这里有两个分配在栈空间的xxxClass指针:Qi和Share指向了堆空间中的同一块内存地址。
内存结构,图解如下:

image

分配在堆中的对象,内存必须由开发者管理。而分配在栈空间上的指针会在其栈帧弹出时自动清理。

OC将堆内存的管理抽象成了一个机制:ARC(Automatic Reference Counting)。在OC中,不需要用mallocfree来分配或释放对象所占的内存。OC在运行期环境中把这部分工作抽象为一套内存管理架构,我们称之为“引用计数”

第2条:在类的头文件中尽量少引用其他头文件

  1. 如果需要引用一个类文件时,只是需要使用类名,不需要知道其中细节,可以用@class xx.h,这样做的好处会减少一定的编译时间。如果是用的#import全部导入的话,会出现a.h import了b.h,当c.h又import a.h时,把b.h也都导入了,如果只是用到类名,真的比较浪费,也不够优雅。

  2. 有时候无法使用@class向前声明,比如某个类要遵循一项协议,这个协议在另外一个类中声明的,可以将协议这部分单独放在一个头文件,或者放在分类当中,以降低引用成本

第3条:多用字面量语法,少用与之等效的语法

传统创建数组方法:

NSArray *languages = [NSArray arrayWithObjects:@"PHP", @"Objective-C", someObject, @"Swift", @"Python", nil];
NSString *Swift = [languages objectAtIndex:2];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"key", @"value", nil];
NSString *value = [languages objectForKey:@"key"];

字面量:

NSArray *languages = @[@"PHP", @"Objective-C", someObject, @"Swift", @"Python"];
NSString *Swift = languages[2];
NSDictionary *dict = @{@"key" : @"value"};
NSString *value = languages[@"key"];
  1. 应该使用字面量语法来创建字符串、数值、数组、字典。与创建此类对象的常规方法相比,这么做更加简明扼要。

  2. 应用通过取下标操作来访问数组下标或字典中的键所对应的元素。

  3. 用字面量语法创建数组或者字典时,若值中有nil,则会抛出异常。务必确保值里不含nil。"arrayWithObjects"会依次处理各个参数直到nil为止,不管后面还有没有值,该方法都会提前结束。
    字面量语法有一个小缺点就是创建的数组,字符串等等对象都是不可变的,如果想要可变的对象需要自己多执行一步mutableCopy,例如

NSMutableArray *languages = [@[@"PHP", @"Objective-C", @"Swift", @"Python"] mutableCopy];

第4条:多用类型常量,少用#define预处理指令

你可能感兴趣的:(iOS 编写高质量Objective-C代码(一))