item 11: 理解 objc_msgSend 的角色

对象调用方法,这个在Objective-C里面叫做传递信息(passing a message)。信息有名称,有方法,接收参数,还可能有返回值。

由于Objective-C是C的一个延展,那么我们首先来看一下C语言中的函数是怎么一回事儿。

C语言中的函数调用被称为static binding,(静态or静止)绑定;意味着被调用的函数在编译时知道。

#import <stdio.h>

void printHello(){

printf("hello");

}

void printByebye(){

printf("byebye");

}

void doOneThing(int type){

if(type==0){

printHello();

}else{

printByebye();

}


}

上述代码在编译的时候,printHello与printByebye都是知道的,编译器发出指定,直接来调用函数。 这些函数的地址已经被有效的硬编程在这些指令中。

换一种方式,如下展示:

#import <stdio.h>

void printHello(){

printf("hello");

}

void printByebye(){

printf("byebye");

}

void doSomething(int type){

void (*func)();

if(type==0){

func=printHello;

}else{

func=printByebye;

}

func();

}

如上所示,在这里,动态绑定被使用上了,因为要调用哪个函数是不知道的;只有在 runtime时。


上述两种情形有何区别呢?

编译器发出指令:

1.在第一种情形下,函数会在 if 和else 语句中都被调用。

2.在第二种情形下,函数只会被调用一次,付出的代价仅是读取这个函数的地址,而不用将其硬编码。


动态绑定是一种机制, 方法被调用,当一个信息传递给了一个object.  所有的方法都是,对于特定的信息哪一个方法被调用,完全决定于runtime;甚至可以改变,这一机制让Objective-C 真正意义上dynamic.

如下所示:

id returnValue=[object  messageName: parameter];

object :接收者 (信息的接收者)

messageName:parameter  (方法selector与参数结合) 这个被称为一个信息。


当看这个消息时,编译器将其转化成标准的C函数,objc_msgSend:

void objc_msgSend(id self,SEL cmd,...)

这是一个参数个数可变化的函数。第一个参数是消息的接收者,第二个参数方法,后面的参数就是原来信息中的参数列表,按顺序依次罗列。

上面的:

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

objc_msgSend函数调用正确的方法,取决于接收者的类型和方法。 为了做到这些,objc_msgSend首先会在接收者的方法列表中去找这个方法,如果找到,将会跳到这个方法的实现中去;如果没有找到,objc_msgSend会一路向上找其父类是否有这个方法。如果还是没有找到方法,message forwarding kicks in. 哈哈!item 12

当一个方法被调用时,看上去好像有很多事情要做。幸运地是,objc_msgSend 会缓存这个结果fast map,所以在未来给相同的类发相同的消息时,会执行地很快。

但是 fast map path 与 statically bound function 调用 相比,还是会慢一些。;

但是如果cach下来了,比静态绑定的函数慢不了多少。

实际情况下,信息调用派遣在一个应用中并不是瓶颈。如果它是的话,那么我们还不如去直接用C语言去写呢,将oc 对象的任何状态传递给它。


前述方法仅适用于某些信息。额外的函数 暴露给了 Objective-C的  runtime 来去处理某些情况:

objc_msgSend_stret

对于某些信息,返回一个struct(结构体)。 这个函数只能处理 适应CPU 寄存器类型 的返回值。 

        objc_msgSend_fpret

对于那些返回值为浮点数的信息。一些architectures需要在函数调用之间对浮点寄存器进行特殊处理,意味首objc_msgSend不是足够好。 这个函数存在的意义是:处理这些奇怪的事情,如x86上面。

        objc_msgSendSuper

 如果将信息传给了父类,例如:[super message:parameter]; 


在上面,我暗指了 objc_msgSend

//todo! 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值