【iOS】objc_msgSend

2017-03-03  本文已影响0人  修炼一颗真心

Objective-C 中对象调用方法叫做“传递消息”,给某对象发送消息相当于在该对象上调用消息方法。消息有“名称(name)”和“selector”,可以传入参数,也可以有返回值。

首先介绍几个概念:

绑定

绑定是方法的调用与所在的类关联起来。绑定分为静态绑定和动态绑定或称为前期绑定和后期绑定。

静态绑定

前期绑定 在程序执行前方法已被绑定,在编译期就能决定运行时所应调用的函数。

动态绑定

后期绑定 在运行时根据具体对象进行绑定。
动态绑定过程:1,虚拟机提取对象的实际类型的方法表 2,虚拟机搜索方法名;3,调用方法。
在 Objective-C 中,如果向某对象传递消息,那就会使用动态绑定机制来决定需要调用的方法,对象收到消息之后,究竟调用哪个方法完全于运行期决定,甚至可以在程序运行时改变,所以使得Objective-C成为一门真正的动态语言。
消息传递机制中的核心函数:
void objc_msgSend(id self,SEL cmd,...)
第一个参数代表接受者,第二个参数代表选择子(SEL),后续参数就是消息中的那些参数。
给对象发送消息:
id returnValue = objc_msgSend(someObject,@selector(messageName:),parameter);
objc_msgSend函数根据接受者和选择子(SEL)类型调用合适的方法。
在接受者所属的类中搜寻其“方法列表”,若有名称相符的方法就跳转实现代码,若无则沿着继承体继续上找找到合适的方法后跳转,如果最终未找到就执行消息转发操作。
如上所述想要掉一个方法要执行很多步骤,幸好objc_msgsend会将匹配到的方法存入“快速映射表”里,每个类都有一块这样的缓存。

特殊消息的调用

尾调用优化

如果函数的最后一项操作仅仅是调用另外一个函数,而无返回值时,就可执行尾调用优化技术。执行前一个函数后编译器会生成调转至另一个函数的指令码,而不会像调用堆栈中推入新的“栈帧”。若不这样做每次调用OC方法前,都需为调用objc_msgSend函数准备“栈帧”,会容易出现“栈溢出”现象。

总结要点

上一篇下一篇

猜你喜欢

热点阅读