2016笔记——Runtime(四)

objc_msgSend函数的深入解析:

屏幕快照 2016-04-13 17.23.42.png

第一个参数是一个id类型的参数,可以为任何对象或者类。

第二个参数是一个SEL类型的参数。

那么SEL又是什么?

SEL是对方法的一种封装,展示的是方法名或者说是签名,方法的真正实现在IMP中,接下来我们看一下方法的链表是什么样子:

屏幕快照 2016-04-14 09.06.27.png

下面是重点了,我们仔细看一下在OC中传递一个消息的流程。

调用一个objc_msgSend( id receiver ,SEL selector ,...)方法系统执行的步骤:

1、

判断receiver是否为nil,如果是nil的话,则不往下执行,返回nil。这就是为什么在OC中向一个nil发送消息不会引起崩溃的原因。

2、

从方法的缓存中查找,被调用过的方法会存在缓存里面,每个类都会有一个表来存被调用过的方法,以便下次更快的调用。

3、

从本类的方法表(dispatch table)中查找方法selector,找到则写入缓存,返回方法。否则就到父类中查找方法,直到基类。如果找不到则执行方法的动态解析。

4、

方法的动态解析:调用+(BOOL)resolveInstanceMethod:(SEL)sel方法来查看是否能够返回一个selector,如果存在则返回selector。不存在则进入下一步。

5、

备用接收者:- (id)forwardingTargetForSelector:(SEL)aSelectro这个方法来询问是否有接收者可以接收这个方法,如果有人接收,则交给它处理,就好像什么都没发生过一样。

6、

方法的转发:如果到了这一步还不能够找到相应的Selector的话,就要进行完整的方法转发过程。调用方法-(void)forwardingInvocation:(NSInvocation*)anInvocation

7、

如果还没有找到方法就GG了,这时候就会抛出 unrecognized selector sent to instance 0x10001fdd0 的错误了。

你可能感兴趣的:(2016笔记——Runtime(四))