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. 当前类的方法列表中查找

如果一直找到没有了父类,说明方法根本不存在,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. 方法解析没用,就到方法转发

原文地址:https://blog.csdn.net/squallmouse/article/details/123204982

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_6007.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注