Objective-C的“obj performSelector”vs objc_msgSend()?

时间:2012-09-03 03:18:01

标签: objective-c ios cocoa

通过Apache Cordova的源代码,我遇到了两行令我困惑的代码:

    //[obj performSelector:normalSelector withObject:command];
    objc_msgSend(obj,normalSelector,command);

从Apple的文档来看,这两种方法之间似乎没有太大区别。

id objc_msgSend(id theReceiver,SEL theSelector,...) 将带有简单返回值的消息发送到类的实例。

- (id)performSelector:(SEL)aSelectorwithObject:(id)anObject 以对象作为参数向接收方发送消息。 (所需的)

这两种方法之间究竟有什么区别?在上面的例子中,两者都发送带有对象作为参数的消息给接收对象。

2 个答案:

答案 0 :(得分:13)

你问两个“方法”之间的区别,但其中只有一个实际上是一种方法。 objc_msgSend函数是一个函数。不是一种方法。

当您在Objective C中的任何对象上调用任何方法时,objc_msgSend函数是实际调用的函数。例如,以下两个基本等效:

// This is what the compiler generates
objc_msgSend(obj, @selector(sel:), param);

// This is what you write
[obj sel:param];

// You can check the assembly output, they are *almost* identical!

这里的主要区别是objc_msgSend没有被编译器检查类型 - 或者至少,它的参数不会根据选择器的参数类型进行类型检查。所以以下大致相同:

[obj performSelector:normalSelector withObject:command];
objc_msgSend(obj, @selector(performSelector:withObject:),
             normalSelector, command);

但是,这有点浪费,因为所有performSelector:withObject:都会调用objc_msgSend

HOWEVER:您应该远离obc_msgSend,因为它不是类型安全的,如上所述。所有apache开发人员正在做的是删除一个方法调用,这在大多数情况下只会给你非常轻微的性能优势。

答案 1 :(得分:7)

注释掉的行是正确的,objc_msgSend()行不正确,因为它需要显式输入(有时候varargs与某些平台上的非varargs函数调用不兼容)。

他们有效地做同样的事情。实际上,方法调用版本只是objc_msgSend()的包装。