【问题标题】:Objective-C's "obj performSelector" vs objc_msgSend( )?Objective-C 的“obj performSelector”与 objc_msgSend()?
【发布时间】:2012-09-03 11:38:49
【问题描述】:

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

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

【问题讨论】:

    标签: objective-c ios cocoa


    【解决方案1】:

    您问的是两种“方法”之间的区别,但其中只有一种实际上是一种方法。 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: 所做的只是调用objc_msgSend

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 2019-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-04
        相关资源
        最近更新 更多