11

Apache Cordovaのソースコードを調べてみると、困惑している2行のコードに遭遇しました。

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

Appleのドキュメントから、これら2つの方法の間に大きな違いはないようです。

id objc_msgSend(id theReceiver、SEL theSelector、...) 単純な戻り値を持つメッセージをクラスのインスタンスに送信します。

-(id)performSelector:(SEL)aSelectorwithObject:(id)anObject オブジェクトを引数として受信者にメッセージを送信します。(必要)

これら2つの方法の違いは正確には何ですか?上記の場合、どちらも受信オブジェクトへの引数としてオブジェクトを使用してメッセージを送信しています。

4

2 に答える 2

14

2つの「メソッド」の違いを尋ねていますが、実際にはそのうちの1つだけがメソッドです。objc_msgSend関数は、まあ、関数です。方法ではありません。

このobjc_msgSend関数は、 Objective Cの任意のオブジェクトで任意のメソッドを呼び出すときに実際に呼び出す関数です。たとえば、次の2つは基本的に同等です。

// 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開発者が行っているのは、単一のメソッド呼び出しを削除することだけです。これにより、ほとんどの場合、パフォーマンスがわずかに向上するだけです。

于 2012-09-03T03:31:41.480 に答える
7

コメントアウトされた行は正しいですが、objc_msgSend()明示的に入力する必要があるという点でこの行は正しくありません(varargsは、一部のプラットフォームでの非varargs関数呼び出しと互換性がない場合があります)。

事実上、彼らは同じことをします。実際、メソッド呼び出しバージョンは単なるラッパーobjc_msgSend()です。

于 2012-09-03T03:26:14.197 に答える