《iOS开发进阶》第19章:Objective-C对象模型

这一章主要介绍了Objective-C对象模型的实现细节,以及Objective-C语言对象模型中对isa swizzling和method swizzling的支持。

1、isa指针

Objective-C是一门面向对象的编程语言,每一个对象都是一个类的实例。在Objective-C语言的内部,每一个对象都有一个名为isa的指针,指向该对象的类。每一个类描述了一系列它的实例的特点,包括成员变量的列表,成员函数的列表等。每一个对象都可以接收消息,而对象能够接收的消息列表保存在所对应的类中。

我们可以在NSObject的定义头文件中看到,NSObject就是一个包含isa指针的结构体。

在runtime.h头文件中,我们可以看到也是一个包含isa指针的结构体,除了isa还有其他成员变量,那只是为了兼容非2.0版的Objective-C的遗留逻辑。

因为类是一个对象,所以它也必须是另一个类的实例,这个类就是元类(metaclass)。元类保存了类方法的列表,当一个类方法被调用时,元类会首先查找它本身是否有该类方法的实现,如果没有,则该元类会向它的父类查找该方法,这样可以一直找到继承链的头。

元类也是一个对象,元类的isa指针都会指向一个根元类(root metaclass)。根元类本身的isa指针指向自己,这样就形成了一个闭环。

 

2、类的成员变量

如果把类的实例看成是一个C语言的结构体,那么isa指针就是这个结构体的一个成员变量,而类的其它成员变量依次排列在结构体中。

Category实现的原理是通过修改一个名为methodLists的指针的指针,可以动态地为某一个类增加成员方法。而通过objc_setAssociatedObject和objc_getAssociatedObject方法可以变现的给对象增加成员变量,但由于实现机制不一样,所以并不是真正改变了对象的内存结构。

另外因为isa也是一个指针,所以除了对象的方法可以动态地修改外,我们也可以在运行时动态的修改isa指针,达到替换对象整个行为的目的。

 

3、对象模型的应用

3.1 动态创建对象

我们可以使用Objective-C语言提供的与runtime相关的函数,动态的创建一个新的类,并且通过相关方法来获得isa指针,从而了解对象的内部结构。

我们可使用objc_allocateClassPaid方法创建新的类,可以使用class_addMethod方法来给类增加新的方法,可以使用objc_registerClassPair来注册新的类,可以使用object_getClass方法来获得对象的isa指针所指向的对象。

3.2系统相关API及应用

isa swizzling的应用,系统提供的KVO的实现,就是利用了动态修改isa指针的值得技术。

Objective-C提供了以下API来动态替换类方法或实例方法的实现:

class_replaceMethod替换类方法的定义。当需要替换的方法有可能不存在时,可以考虑使用该方法。

method_exchangeImplementations交换两个方法的实现。当需要交换两个方法的实现时使用。

method_setImplementation设置一个方法的实现。当仅仅需要为一个方法设置其实现方式时使用。

 

在开源界的使用

AFNetWorking使用了class_replaceMethod方法。

Nimbus在其core模块中提供了NIRuntimeClassModifications.h文件,用于提供上述API的封装。

大众点评客户端,WaxPatch可实现通过修改服务器更新来动态修改客户端的逻辑。而WaxPatch主要是修改了Wax的wax_instance.m文件,在其中加入了class_replaceMethod来替换原有实现,从而修改客户端的原有行为。

 

本文来自Awnlab.com麦芒实验室,转载请注明出处,谢谢合作。