Runtime
2019-08-12 本文已影响0人
皮蛋豆腐酱油
一.内容
SEL
objc_msgSend函数
方法缓存
二.方法编号
1.oc 选择子表
2.如果没有找到,自动创建一个SEL,添加到选择子表当中
三.objc_msgSend函数
当我们“调用”方法时,在OC中称之为传递消息,对象接收到消息后,会去“方法列表“中寻找,本类中找不到则向上找,如果一直找不到,则进行”消息转发“。那么OC是如何进行消息传递的呢?在OC中,所有的方法底层都是C语言的函数,当我们向一个对象发送一条消息时,编译器会将其转换为一个C函数 objc_msgSend(),这个函数会动态帮我们绑定要执行的函数。
不是所有的消息传递都会变成objc_msgSend, 还有一些其他的如objc_msgSendSuper, objc_msgSend_stret,取决于当前要发送消息的对象,大部分是objc_msgSend。
会先查找缓存,没有则会调用objc_msgSend_uncached,objc_msgSend_uncached最终会执行_class_lookupMethodAndLoadCache3,
_class_lookupMethodAndLoadCache3在runtime当中是有具体实现的。_class_lookupMethodAndLoadCache3最终调用了lookUpImpOrForward
如果缓存没有命中:
- 类对象当中的方法列表查找对象Method_t(method_t.name == sel),如果方法列表有序就二分查找,无序则遍历
- 沿着继承链查找当前类对象的方法列表
- 消息转发机制
①首先动态决议,允许我们动态地添加方法,调用_class_resolveMethod,这个方法里面会判断是不是元类,如果不是,就调_class_resolveInstanceMethod
,如果是就调_class_resolveClassMethod,接下来调lookUpImpOrNil,lookUpImpOrNil里面会调lookUpImpOrForward
②消息转发
_objc_msgForward_impcache(触发消息转发机制),分为两部分,forwardTargerForSelector和forwardInvocation
③方法缓存
objc_class:cache_t:buckets_t(是一个散列表)
四.分类为什么不能添加成员变量
属性 = get + set + _ivar
这个变量 _ivar存放在objc_class结构体当中,objc_class在编译时期对于它的成员变量的空间就已经决定好了
分类是运行时决议的