理解 objc_msgSend 的角色

来源:互联网 发布:js判断ios android 编辑:程序博客网 时间:2024/05/21 09:27

对象调用方法,这个在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 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
原创粉丝点击