Objective-C Runtime学习笔记

来源:互联网 发布:sql where语句 1,4 编辑:程序博客网 时间:2024/05/01 19:53

1.objc_msgSend函数

在Objective-C(以下简称OC)中,消息只有在运行期间才会绑定到具体的方法实现。编译器会将一个发送消息转为一个C函数,例如[receiver message]会转为objc_msgSend。此函数将receiver和message作为两个主要的参数。也即objc_msgSend(receiver, message)。此函数则可以在运行期进行动态绑定。主要过程包括一下三个:
①首先找到message指向的方法实现。由于同一个方法名称可能在不同的类中有实现,objc_msgSend通过receiver找到正确的方法;
②然后调用方法,将方法及其参数发送给receiver;
③最后,将方法的返回值作为自己的返回值。
根据苹果官方文档注明的,我们不能直接调用此方法。

消息转发是建立在编译器为每个类和对象所建立的结构基础上的,每个类包括了两个基本的元素(elements):
①一个指向父类的指针。
②一个类转发表(dispatch table)。这个表是消息选择器(selector)及与之相关联的消息地址的入口。

下图是类和对象架构的原理图
消息发送
当一个新的对象被创建,并分配内存,它的实例变量被初始化。第一个实例变量是一个名叫isa的指针,它指向自己的类结构(class structure)。它使对象能够操作(access)自己的类以及父类。

当一个消息被发送时,消息发送函数通过isa指针去找到类,并在这个类的转发表中去寻找这个方法,如果在此类中没有找到此方法,objc_msgSend则会顺着指针往父类的转发表中查询,如果父类依然找不到,则会顺着继承树往上继续查找,一直查找到NSOjbect类。

2.获取消息地址
如果不想在运行期进行动态绑定,则可以获取消息地址进行直接调用。可以通过方法methodForSelector:来获取指向消息的指针。以下是代码示例:

//声明一个指向函数的指针settervoid (*setter)(id, SEL, BOOL);int i;//通过方法methodForSelector获取selector的函数地址setter = (void (*)(id, SEL, BOOL))[target methodForSelector:@selector(method)];//循环调用method 100次for (i = 0; i < 100; i++) {    setter(targetList[i], @selector(method), YES);}

3.给类动态添加方法

我们还可以给类动态添加方法,代码如下

+ (BOOL)addMethods:(SEL)aSEL {    class_addMethod([self class], aSEL, (IMP)dynamicMethodIMP, @"v@:");}

class_addMethod第一个参数指定方法添加到哪个类, aSEL为方法名称,
IMP是implementation的简称,指向具体实现的地址,他必须接受两个参数:self 和 _cmd。例如:

void dynamicMethodIMP(id self, SEL _cmd) {}

0 0