11

在浏览 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 以对象作为参数向接收者发送消息。(必需的)

这两种方法究竟有什么区别?在上述情况下,两者都将带有对象作为参数的消息发送给接收对象。

4

2 回答 2

14

您在问两种“方法”之间的区别,但其中只有一个实际上是一种方法。该objc_msgSend功能是一个功能。不是方法。

objc_msgSend函数就是你在Objective C中对任意对象调用任意方法时实际调用的函数。例如下面两个基本等价:

// 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:的都是 call objc_msgSend

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

于 2012-09-03T03:31:41.480 回答
7

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

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

于 2012-09-03T03:26:14.197 回答