概述
文章目录
- 1. 消息发送的本质
- 2.消息发送流程
- 1. _objc_msgSend
- 2. CacheLookup (快查找,在缓存中查找方法)
- 3. __objc_msgSend_uncached
- 3. 消息慢查找(lookUpImpOrForward)
- 1. 定义消息转发
- 2. 把类和父类都实现了
- 3. 当前类的方法列表中查找
- 4. 父类中查找
- 5. 找到方法 goto done
- 4. 总结
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. 总结
- 当执行方法时,转换成objc_msgSend
- 在汇编语言中, _objc_msgSend 是入口,方法会由 CacheLookup 方法去cache缓存中查找
如果找到了,就直接执行
如果没有找到,就会执行 __objc_msgSend_uncached 方法,从而转到C语言中的lookUpImpOrForward
- 从当前类的方法列表中查找
找到了就执行(返回IMP),且存入缓存
没找到就到父类的缓存中查找,然后再在方法列表中查找
- 知道再也没有父类了,执行方法解析
- 方法解析没用,就到方法转发
最后
以上就是个性苗条为你收集整理的09.04-消息发送的全部内容,希望文章能够帮你解决09.04-消息发送所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复