2009-07-08 18 views
9

私はObjectiveCを学習しており、イントロスペクションに関する問題に遭遇しました。基本的には、オブジェクトの配列をループして、lowercaseStringセレクタを受け入れるかどうかを判断しています。もしそうであれば、私はオブジェクトのセレクタを呼び出します。オブジェクトがそのセレクタに応答したことを確認したら、それを呼び出します。 "警告: 'NSObject;' -lowercaseString 'に応答しない可能性があります。"NSObject"が '-someMethod'に応答しない可能性があります警告:

コードは書かれているようにうまく動作しますが、私は警告を受け取りたくありません。警告が表示されないようにする(つまり警告をオフにすることなく)「正しい」方法があると仮定しています。何か案は?

NSMutableArray *myArray = [[NSMutableArray alloc] init]; 

[myArray addObject:@"Hello!"]; 
[myArray addObject:[NSURL URLWithString:@"http://apple.com"]]; 
[myArray addObject:[NSProcessInfo processInfo]]; 
[myArray addObject:[NSDictionary dictionary]]; 

SEL lowercaseSelector = @selector(lowercaseString); 

for (NSObject *element in myArray) { 
    if ([element respondsToSelector:lowercaseSelector]) { 
     NSLog([element lowercaseString]); // Warning here 
    } 
} 
+0

また、「セレクタ」用語が間違っている場合は、私を修正してください。 :) – Tyson

+3

*非定数文字列をNSLogに渡しません。セキュリティ上のリスクがあります。あなたはこのケースではあなたが安全だと思うかもしれませんが、それを習得しないでください。あなたは必然的にセキュリティホールを開いた場合にそれをやることになります。 – kperryua

+0

このセキュリティホールに関する詳細情報へのリンクはありますか?私は間違いなくそれについてもっと読むことに興味があります。 – Tyson

答えて

15

をまた、オブジェクトの任意の型であるidを使用することができます。

for (id element in myArray) { 
    if ([element respondsToSelector:lowercaseSelector]) { 
     NSLog([element lowercaseString]); 
    } 
} 
+0

私はNSObjectが適切なものだと考えましたが、確かにidはそれを実行するためのよりよい方法です。 – Tyson

+0

要素の保持または解放を呼び出す必要がない限り、 –

+0

idでretai/releaseを呼び出すと何が問題になりますか? –

4

ちょうど関数を呼び出す前に、NSStringのにあなたNSObjectのをキャスト:

for (NSObject *element in myArray) { 
    if ([element respondsToSelector:lowercaseSelector]) { 
     NSLog([(NSString*)element lowercaseString]); // No warning! 
    } 
} 
+0

しかし、オブジェクトがNSStringがサポートするすべてのセレクタをサポートしていない場合はどうなりますか?私のOOPセンスは、それが悪いことを私に伝えます。どのスーパークラスに属しているかに関係なく、セレクタを1つだけチェックしています。 – Tyson

+0

さて、あなたは、-lowercaseStringがNSStringを返すと仮定しています。なぜなら、それはNSLogが書式文字列に対して期待するものなのでです。何らかの理由でNSStringを返さない場合は、フォーマット文字列としてNSString以外のものを渡しているので、NSLogはそれを詰まらせるでしょう。 –

+0

最も安全な方法は、 'lowercaseString'を取得し、それを変数に格納し、NSStringの種類であるかどうかをテストすることです。あなたはおそらく、そのパラノイドである必要はありませんが、もしあなたがいなくても、変数を宣言したり、戻り値を 'NSString *'にキャストしたりするかもしれません。 –

6

performSelector:はどうですか?

SEL lowercaseSelector = @selector(lowercaseString); 

for (NSObject *element in myArray) { 
    if ([element respondsToSelector:lowercaseSelector]) { 
     NSLog([element performSelector:lowercaseSelector]); // No warning 
    } 
} 

これにより、コンパイラの警告が取り除かれます。

+0

ああ、これはそれを行う良い方法のように思えます。応答していただきありがとうございます。 – Tyson

1

idとしてキャスティングすると警告が削除されました。

if ([self.content respondsToSelector:@selector(setDelegate:)]) 
{ 
    [(id)self.content setDelegate:nil]; 
} 
関連する問題