Objective-C的"obj performSelector"vs objc_msgSend()?

nsg*_*nsg 11 cocoa objective-c ios

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

    //[obj performSelector:normalSelector withObject:command];
    objc_msgSend(obj,normalSelector,command);
Run Code Online (Sandbox Code Playgroud)

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

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

- (id)performSelector:(SEL)aSelectorwithObject:(id)anObject 以对象作为参数向接收者发送消息.(需要)

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

Die*_*Epp 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!
Run Code Online (Sandbox Code Playgroud)

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

[obj performSelector:normalSelector withObject:command];
objc_msgSend(obj, @selector(performSelector:withObject:),
             normalSelector, command);
Run Code Online (Sandbox Code Playgroud)

但是,这有点浪费,因为一切performSelector:withObject:都是打电话objc_msgSend.

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


bbu*_*bum 7

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

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