2016笔记——Runtime(二)

上篇不明不白的写了一个方法,虽然实现了,但是不太理解这到底是什么。。坚决寻根问底!

Objective-C runtime是一个实现Objective-C语言的C库。对象可以用C语言中的结构体表示,而方法可以用C函数来实现。这些结构体和函数被runtime函数封装后,Objective-C开发者就可以在程序运行时创建、检查、修改类、对象和它们的方法。

除了封装,Objective-C runtime库也会找出要执行的方法。当程序执行到[object doSomething]这一句时,不会直接找用到方法并调用,而是会发送一条消息给对象(这里称作接收者),runtime库会让该对象去寻找消息并决定该如何响应该消息。

Objective-C语言强调消息的传递而不是方法的调用。因此你可以对一个对象传递任何消息,而不需要在编译期声明这些消息的处理方法。很显然既然编译期并不能确定方法的地址,那么运行期间就需要自行定位了。而Objective-C runtime就是通过

屏幕快照 2016-04-12 11.29.57.png

这个函数来调用方法的。其中id self 是调用对象,SEL op 是方法,省略号就是不定参数。

objc_msgSend函数会依据接收者和方法的类型来调用适当的方法。为了完成此操作,该方法需要在接收者所属的类中搜寻“方法列表”,如果能够找到与选择子名称相符的方法,就跳至该方法的实现代码。若是找不到,那就沿着继承体系继续向上查找,等找到合适的方法之后再跳转。如果始终还是找不到相符的方法,那就执行“消息转发”操作。

流程图如下:

屏幕快照 2016-03-31 15.02.15.png

这么说来,想调用一个方法似乎需要很多步骤,所幸objc_msgSend会将匹配结果缓存在“快速映射表(fast map)”里面,每个类都有这样一块缓存,若是稍后还向该类发送相同的方法消息,那么执行起来就很快了。

objc_msgSend_stret:如果待发送的消息要返回结构体,那么可以交由该函数处理。只有当CPU的寄存器能够容纳下返回的消息时,这个函数才能处理此消息。若是返回值无法容纳于CPU寄存器中(返回的结构体太大了),那么就由另一个函数执行派发。此时,那个函数会通过分配在栈上的某个变量来处理消息所返回的结构体。

objc_msgSend_fpret:如果消息返回的是浮点数,那么可以交由此函数处理。在某些架构的CPU中调用函数时,需要对“浮点数寄存器(floating-point register)”做特殊处理,也就是说上面的objc_msgSend在这种情况下并不能满足需要,就会使用该函数。

objc_msgSendSuper:如果要给父类发消息,比如[super message:param],那么就交给此函数处理。此外还有objc_msgSendSuper_stret函数,用于处理发送给super的相应消息。

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