2011-08-13 10 views
5

従来の手段を使用してクラスインターフェイスで宣言されていないメソッドを呼び出すときに警告が生成されるのはなぜですか?@selectorを使用してメソッドを呼び出すときには警告が表示されません。それはセレクタが自己とは異なる呼び出し元によって実行されるためですか?例えば@codelectorを使用すると、Xcodeが宣言されていないメソッドについて文句を言うのはなぜですか?

-(void) doStuff 
{ 
    [self doNow]; // Warning: instance method not found 
    SEL sel = @selector(doNow); // no warnings 
} 

-(void) doNow {} // this method is not declared in the interface 

答えて

13

"宣言されていないセレクタ" の警告はデフォルトではオフになっています。どうしてか分かりません。 [ビルド設定]で元に戻すことができます。

この設定のためにドキュメントを読み取り:宣言されていないセレクタを参照「@selector(...)」という表現が発見された場合

が警告。セレクタは、その名前のメソッドが@interfaceまたは@protocol宣言で明示的に、または@implementationセクションに暗黙的に "@selector(...)"式の前に宣言されていない場合、宣言されていないとみなされます。このオプションは、 "@selector(...)"式が見つかるとすぐにチェックを実行しますが、-Wselectorはコンパイルの最終段階でのみチェックを行います。これはまた、メソッドとセレクターを使用する前に宣言しなければならないというコーディングスタイルの慣例を強制します。 [GCC_WARN_UNDECLARED_SELECTOR、-Wundeclaredセレクタ]

+1

+1。 –

+0

ありがとうございます。 Appleがこのオプションをデフォルトで無効にしているとは一貫していないようです。 –

4

類似questionはSO数週間前に求められました。

これは基本的にセレクタがレイトバインドされているためです。実行時まで参照されません。コンパイル時に検証を強制するオプションがあります。私がリンクしている質問には、あなたがそれをどうやってできるかという情報がいくつかあります。

2

デフォルトで@selectorの動作は、コンパイラに指示していることです。私を信じて、私のクラスのどこかでこのメソッドを持っています。クラスを含む.hファイルをインポートするのではなく、クラス名を@classするのと同じコンセプトです。

2

そのような呼び出しは、メソッドシグネチャは戻り型を有しているかどうかに応じobjc_msgSend又はobjc_msgSend_stretへの呼び出しのいずれかに変換するので、コンパイラは、(すなわち[self doNow];)を呼び出すためにメソッドのシグネチャを知る必要があるからですstructのいずれかです。 (セレクタ(コロンを含む名前、型はありません)とメソッドのシグネチャ(型)の違いを覚えておいてください)。そうでなければ間違った関数を呼び出す可能性があるので警告する必要があります知っている。

セレクタ(@selector(...))を取得するだけで、型を知る必要はありません。セレクターは単に名前であり、その名前を指定したものです。それはあなたがセレクタを使うためのものです。 performSelector:でそれを使用する場合は、そのメソッドがオブジェクトの引数と戻り値の型を持つメソッドに対してのみ機能するため、型を知る必要はないため、あいまいさはありません。したがって、警告の必要はありません。

関連する問題