09.04-消息发送

1. 消息发送的本质

 		Person *p = [Person new];
//        Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("new"));
        
        [p test];
//      ((void (*)(id, SEL))(void *)objc_msgSend)((id)p, sel_registerName("test"));
// 		objc_msgSend (p,sel_registerName("test"));
  • 通过objc_msgSend(<#id#>, <#SEL, …#>)

第一个 receiver : 消息接受者
第二个 SEL : 方法名
后面跟着参数


2.消息发送流程

1. _objc_msgSend
  • objc-msg-arm64.s

_objc_msgSend 是消息发送的入口
在这里插入图片描述


2. CacheLookup (快查找,在缓存中查找方法)
  • 方法缓存查找

通过CacheLookup 去cache缓存中查找方法

  • 通过散列表来查找方法


如果在cache中 没有找到方法,就跳转到__objc_msgSend_uncached方法中


3. __objc_msgSend_uncached

  • 寻找没有被缓存的方法,在方法列表中查找


lookUpImpOrForward(obj, sel, cls, LOOKUP_INITIALIZE | LOOKUP_RESOLVER)
查找方法的实现(imp)或者消息转发
参数中有 obj , sel(方法名) , cls(类),查找的枚举


3. 消息慢查找(lookUpImpOrForward)

1. 定义消息转发
  • 如果没有找到消息,且没有实现消息解析,就会转发消息


2. 把类和父类都实现了
  • 为了当前类找不到方法后,可以去父类找方法


3. 当前类的方法列表中查找
  • 在当前类的方法列表查找,如果没有找到,把curClass变成父类

如果一直找到没有了父类,说明方法根本不存在,imp变成方法转发方法.


4. 父类中查找

整个for循环的可循环数-1

  • 在父类的cache中找方法
  • 如果找到了, goto done
    如果没有找到,重新开始循环,在方法列表中寻找没有要找的方法

5. 找到方法 goto done

把找到的方法放入缓存cache中
参数是cls , 就是最开始传入的参数
即使是父类中找到的方法,也会存储在当前类的缓存cache中


  • 如果没有找到,就会到方法解析环节

4. 总结

  1. 当执行方法时,转换成objc_msgSend
  2. 在汇编语言中, _objc_msgSend 是入口,方法会由 CacheLookup 方法去cache缓存中查找

如果找到了,就直接执行
如果没有找到,就会执行 __objc_msgSend_uncached 方法,从而转到C语言中的lookUpImpOrForward

  1. 从当前类的方法列表中查找

找到了就执行(返回IMP),且存入缓存
没找到就到父类的缓存中查找,然后再在方法列表中查找

  1. 知道再也没有父类了,执行方法解析
  2. 方法解析没用,就到方法转发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值