IOS OC objc_msgSend的做用

一 消息传递


    OC中调用方法也叫消息传递(pass a message),消息有名称(name) 或 选择子(selector),能够接受参数,并且能够设定返回值。缓存


    OC中向某对象传递消息,会使用动态绑定机制来决定须要调用的方法,在底层,全部方法都是普通的C语言函数,然而对象受到信息以后,究竟调用什么方法则彻底完成于运行期决定,甚至可用在程序运行时改变,这些特性使得OC为动态语言。给对象发送消息的写法:架构

id returnValue = [object messageName:parameter];

    returnValue     是 返回值函数

    object             是 接受者(receiver)
优化

    messageName 是 选择子(selector)spa

    选择子与参数合起来称为消息。指针


     编译器看到 [object messageName:parameter] 消息后会转换为标准的C语言函数调用,所调用函数是消息传递机制中的核心函数,objc_msgSend,其原型以下:code

void objc_msgSend(id self,SEL cmd, …);

    这是个“参数个数可变的函数”,能接受多个参数,第一个参数表明 接受者,第二参数表明选择子(SEL 就是选择子的类型,选择子就是方法名),后续参数就是消息中的那些参数,其顺序不变。
对象




二消息调用过程


编译器会把刚才例子中的消息转换成如下函数继承

id = returnValue = objc_msgSend(someObject,@selector(messageName:),parameter);

    objc_msgSend 函数会依据接受者与选择子的类型来调用适当的方法,为了完成此操做,该方法须要在接受者所属的类中搜寻其“方法列表”,若是能找到与选择子名称相符的方法,就跳至其实现代码。如果找不到,那就沿着继承体系继续向上查找,等找适合的方法以后再跳转,若是最终仍是找不到相符的方法,那就执行“消息转发”操做(下篇讲),调用一个方法须要不少步骤,为了简化开销,objc_msgSend会将匹配结果缓存在“快速映射表”里面,每一个类都有这样一块缓存,在稍后向该类发送选择子相同的消息,执行效率会很快。cmd




三 非objc_message 状况

    objc_msgSend_stret  若是待发送的消息要返回结构体,由该函数处理。只有当CPU寄存器可以容纳下返回类型时,该函数才会处理。若是不能容纳,则由另外一个函数执行派发

    objc_msgSend_fpret 若是返回的浮点数,由该函数处理,在某些架构的CPU中调用函数,须要堆“浮点数寄存器”作特殊处理。

    objc_msgSendSuper 若是要给超类发消息,例如[super message:parameter],由该函数处理。




四 尾调用优化

    上面提到objc_msgSend 等函数找到调用方法实现后,会“跳转过去”,之因此能这样作,是由于OC 对象的每一个方法均可以视为简单的C函数,原型以下

<return_type> Class_selector(id self,SEL _cmd,…)

    每一个类里都有一张表格,其中的指针会指向这种函数,二选择子的名称则是查表时所用的“键”。ojbc_msgSend 等函数正是经过该表来寻求应该执行的方法并跳转到实现。上面的原型和objc_msgSend 函数很像,是位了利用“尾调用优化”技术,令“跳转到方法实现”操做变得更简单。

    若是函数的最后操做是调用另外一个函数,就会运用到“尾调用优化”,编译器会生成调转至另外一个函数所需的字节码,并且不会像调用堆栈中推入新的“栈幀”,只有当函数最后一个操做是调用其余函数而不会将其返回值另做他用时,才能执行“尾调用优化”,改技术避免了过早发生”栈溢出”现象




五 总结

  •     消息由接受者,选择子以及参数构成,给某个对象发送消息,也就至关于在该对象上 调用方法。

  •     发给某对象的所有消息都须要由 动态消息派发系统 来处理,该系统会查出对应的方法,并执行其代码。


详细请查阅《Effective Objective-c 2.0》

相关文章
相关标签/搜索