OC消息机制

1 OC消息机制

OC对象调用方法在编译阶段不知道具体的方法在哪里,是在运行的过程中,向对象发送消息,通过对象得到函数地址,调用函数,如果没有找到,则抛出异常。
OC中方法调用,其实都是转成了objc_msgSend函数的调用, 给receiver 【方法调用者】 发送了一条消息 【selector 方法名】。

objc_msgSend 底层有3大阶段:

  • OC 消息发送
  • 动态方法解析
  • 消息转发

类的数据结构: 类对象中,存储着isa, superclass , 属性、对象方法、协议、成员变量等

struct objc_class {
Class isa; //类的isa指向它的metaclass
Class superclass; //指向类的超类
cache_t cache; // 方法缓存 - 方法缓存列表,散列表(哈希表)数据结构,缓存自己之前调用过的方法,指向最近使用的方法的指针,用于提升效率
class_data_bits_t; // 获取具体的类信息
}

2 OC消息发送

如何通过对象找到调用函数的地址?
[selector 方法名]会返回一个SEL变量,这个变量是char *的形式将方法对应为唯一的值,以键值对的形式存储函数地址。类对象中的isa就是指向对象的类的指针isa。

发送过程:
1、在程序运行时会给每个类的结构体分配一块空间,对象的isa指向的就是这块空间
2、当发送调用方法的消息后,根据receiver对象的isa指针获取它对应的class
3、通过SEL查找函数,优先在class的cache查找message方法,如果找不到,再到methodLists查找,若还不能找到,再去superClass中查找,找到后会将method放到对应objc_class的cache中,方便下次查找。
4、一旦找到message这个方法,再依据receiver 中的self 指针找到当前的对象,调用当前对象的具体实现的方法(IMP),然后传递参数,调用实现方法。

在这里插入图片描述

当对象收到无法解读的消息的时候,则需要启动消息转发。

1、首先判断调用的方法对象是否为nil, 如果为nil,则直接退出,通过实例对象的isa 找到类对象,在类对象的cache 列表中查找,如果找到直接调用,
2、如果cache 列表中没有,则在这个类对象的方法列表中查找,如果找到调用,并将此方法放在自己的cache 中,方便之后查找
3、如果类对象方法列表中没有,则通过类对象的superclass 指针,找到父类的类对象, 先cache 中查找,再方法列表中查看。如果在父类中找到了方法,则调用,并将方法缓存到自己的cache中,方便之后查找。
4、如果superclass 为nil, 则进入动态方法解析阶段。

3 OC动态方法解析

1、首先会判断是否进入过动态方法解析阶段,

  • 如果进入过则直接进入下一步,消息转发
  • 如果没有进入,则会进入这个方法解析阶段,会调用 - resolveInstanceMethond; 在这个方法里面实现代码,之后将这个动态方法解析阶段标记为执行过的状态。

2、动态解析过后,会重新走消息发送的流程,如果找不到方法会再次进入resolveInstanceMethond方法,此时已经标记过了,直接进入一下个阶段:消息转发

4 OC消息转发

绘图中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Αиcíеиτеǎг

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值