最近在读一本effecttive Objective-C 2.0 ---- 编写高质量iOS与OS X代码的52个有效方法
笔者在这里记录一些比较好用的方法和技巧,如有错误或者疏漏,欢迎大家指正.
1. 首先简单介绍一下Objectice-C这门语言.
Objective-C通过一套全新的语法, 在C语言基础上添加了面向对象特性,Objective-C的语法中频繁使用方括号,而且不吝啬写出极长的名字,这通常令许多人觉得此语言比较冗长,其实这样写出来的代码十分易读,只是C++或许Java程序员不太适应.
2. 该语言使用消息结构(messaging structure) 而非函数调用(function calling).Object-C语言由Smalltalk演化而来,后者是消息型语言的鼻祖.消息与函数调用之间的区别看上去就像这样:
// Messaging (Objective-C)
Object *obj = [Object new];
[obj performWith: parameter1 and: parameter2];
// Function calling (C++)
Object *obj = [Object new];
obj->perform(parameter1, parameter2);</span>
关键的区别在于:使用消息结构的语言, 在其运行时所执行的代码由运行环境来决定;而使用函数调用的语言,则由编译器决定.如果范例代码中调用的函数是多态的,那么在运行时就要按照虚方法表(编程语言为实现动态派发或运行时方法绑定而采用的一种机制)来查出到底该执行哪个函数实现.而采用消息结构的语言,不论是多态,总是在运行时才会去查找所要执行的方法.接受消息的对象问题也是在运行时处理,其过程叫做(动态绑定)
3. Object-C的重要工作都是由"运行期组件"而非编译器完成的.使用Objective-C的面向对象特性所需的全部数据结构及函数都是在运行期组件里面.举例来说, 运行期组件中含有全部的内存管理方法.运行期组件本质上就是一种与开发者所编写代码相链接的动态库,其代码能把开发者编写的所有程序结合起来.
4.Object-C是C的超集, 所以C语言中的所有功能在编写OC代码时依然适用.因此必须同时掌握OC与C的核心概念,才能写出高效的OC代码,尤其重要的是C语言的内存模型,这有助于理解OC的内存模型以及引用计数机制的工作原理,同时要明白OC语言中的指针是用来指示对象的,
NSString *someString = @"The string";
这种语法基本上就是照搬C语言的,声明了一个名为someString的变量,类型是NSString类型,此变量为指向NSString的指针.所有的OC语言的对象都必须这样声明,因为对象所占内存总是分配在堆空间中,而绝对不会分配在栈区,不能在栈上分配OC对象: NSString stackString;
someString的变量指向分配在堆里的某块内存,其中包含NSString对象.如果再创建一个对象指向同一个地址,那么两个变量会同时指向此对象.一个分配在堆中的NSString的实例,然后有两个分配在栈中的指针指向该实例.
分配在堆中的内存必须管理,而分配在栈上用于保存变量的内存会在其栈帧弹出时自动清理.OC将堆内存管理抽象出来,不需要malloc及free来分配或者释放对象所占内存.OC运行期环境把这部分工作抽象在一套内存管理框架,名叫引用计数.
在OC代码中,有不包含*的变量, 它们可能会使用栈空间.这些变量所保存的不是OC对象, 比如CoreGraphics框架中的CGRect的例子: (CGRect 是 C结构体)
<span style="font-size:18px;"> // CGRect 变量
CGRect frame;
frame.origin.x = 0.0f;
frame.origin.y = 10.0f;
frame.size.height = 100.f;
frame.size.width = 150.0f;
</span>
整个系统框架都是在使用这种结构体,因为如果改用OC对象来做的话,性能会受到影响,与创建结构体相比, 创建对象还需要额外的开销.例如分配及释放堆内存等,如果需要保存非对象类型 int float char 等类型,那么通常使用CGRect这种结构体就可以了. 笔者建议: 如果新手编写OC代码的话, 最好先熟悉下C语言的语法, 这会让你解除一些困惑.
总结: OC为C语言添加了面向对象的特性, 尤其是超集. OC使用动态绑定的消息结构, 也就是说, 在运行时才会检查对象类型, 接受一条消息之后, 执行什么代码,由运行环境而非编译器来决定, 理解好C语言的核心概念有助于写好OC程序(内存模型和指针)