1、了解Objective-C语言的起源

Objective-C在C语言的基础上添加了面向对象特性。使用“消息结构”(message structure)而非“函数调用”(function calling)。OC由Smalltalk演化而来,后者是消息型语言的鼻祖。

​ 消息与函数调用的关键区别在于:使用消息结构的语言,其运行时所应执行的代码有运行环境来决定;而使用函数调用的语言,则有编译器决定。

​ Objective-C的重要工作都由“运行期组件”(runtime component)而非编译期来完成。OC面向对象特性所需的全部数据结构和函数都在运行期组件里。

​ Objective-C是C的“超集”(superset),所以C语言中的所有功能在编写Objective-C代码时依然适用。因此必须同时掌握C与OC这两门语言的核心概念,方能写出高效的OC代码来。其中有为重要的是要理解C语言的内存模型(memory model),这有助于理解OC的内存模型及其“引用计数”(reference counting)机制的工作原理。需明白OC中的指针是用来指示对象的。想要声明一个变量,令其指代某个对象,可用如下语法:

NSString *string = @"Hello world";

​ 这种语法基本上是照搬C语言的,它声明了一个名为string的变量,其类型是NSString*。也就是说此变量为指向NSString的指针。所有OC语言的对象都必须这样声明,因为对象所占内存总是分配再“堆空间”(heap space)中,而绝不会分配在“栈”(stack)上。

​ 如下两个指针指向同一个内存地址:

NSString *str1 = @"Hello world";
NSString *str2 = str1;

​ 只有一个NSString实例,两个变量指向此实例,两个变量都是NSString*型。及当前”栈帧“(stack frame)里分配了两块内存,每块内存大小都能容下一枚指针(在32位机器上是4字节,64位上是8字节)。这两块内存里的值都一样,就是NSString实例的内存地址。

​ 分配在堆中的内存必须直接管理,而分配在栈上用于保存变量的内存则会在其栈帧弹出时自动清理。OC将堆内存管理抽象出来,不需要用malloc及free来分配或释放对象所占内存。OC运行期环境把这部分工作抽象为一套内存管理架构:“引用计数”。

​ 在OC代码中,有时候会遇到定义里不含*的变量,它们可能会使用“栈空间”(stack space)。这些变量所保存的不是OC对象。如:CoreGraphics框架中的CGRect:

CGRect frame;
// CGRect是C结构体,定义如下:
struct CGRect {
  CGPoint origin;
  CGSize size;
};
typedef struct CGRect CGRect;

​ 整个系统框架都在使用这种结构体,因为改用OC对象来做的话,性能会受影响。与创建结构体相比,创建对象还需要额外开销(如:分配及释放堆内存等)。如果只需保存int、float、double、char等“非对象类型”(nonobject type),那么通常使用CGRect这种结构体就可以了。

要点:

  • OC为C语言添加了面向对象特性,是其超集。OC使用动态绑定的消息结构。及在运行时才会检查对象来袭,接收一消息后,究竟应执行何种代码,由运行期环境而非编译期决定

  • 理解C语言的核心概念有助于写好OC程序,尤其要整我内存模型与指针

Last updated

Was this helpful?