web-dev-qa-db-ja.com

Objective-C:複数の引数を使用してセレクターを呼び出す

MyClass.mで、定義しました

- (void) myTest: (NSString *) withAString{
    NSLog(@"hi, %@", withAString);
}

myClass.hの適切な宣言。後で電話したい

[self performSelector:@selector(mytest:withAString:) withObject: mystring];

myClass.mで*キャッチされない例外 'NSInvalidArgumentException'によるアプリの終了、理由: '*-[MyClass myTest:withAtring:]:インスタンス0xe421f0に送信された認識されないセレクター

私は、コンソールに文字列を出力する引数を取らず、問題なく動作するセレクタを使用して、より簡単なケースを試しました。コードの何が問題になっていますか?どうすれば修正できますかありがとう。

138
Stu

メソッドのシグネチャは次のとおりです。

- (void) myTest:(NSString *)

withAStringはたまたまパラメーターです(名前は誤解を招くもので、セレクターの署名の一部のように見えます)。

この方法で関数を呼び出す場合:

[self performSelector:@selector(myTest:) withObject:myString];

それが動作します。

ただし、他のポスターが示唆しているように、メソッドの名前を変更することもできます。

- (void)myTestWithAString:(NSString*)aString;

そして呼び出し:

[self performSelector:@selector(myTestWithAString:) withObject:myString];
134

Objective-Cでは、セレクタの署名は次のもので構成されます。

  1. メソッドの名前(この場合は「myTest」になります)(必須)
  2. メソッドに入力がある場合、メソッド名に続く「:」(コロン)。
  3. 追加の入力ごとに名前と「:」。

セレクタには次の知識がありません。

  1. 入力タイプ
  2. メソッドの戻り値の型。

次に、performMethodsViaSelectorsメソッドがセレクターを介して他のクラスメソッドを実行するクラス実装を示します。

@implementation ClassForSelectors
- (void) fooNoInputs {
    NSLog(@"Does nothing");
}
- (void) fooOneIput:(NSString*) first {
    NSLog(@"Logs %@", first);
}
- (void) fooFirstInput:(NSString*) first secondInput:(NSString*) second {
    NSLog(@"Logs %@ then %@", first, second);
}
- (void) performMethodsViaSelectors {
    [self performSelector:@selector(fooNoInputs)];
    [self performSelector:@selector(fooOneInput:) withObject:@"first"];
    [self performSelector:@selector(fooFirstInput:secondInput:) withObject:@"first" withObject:@"second"];
}
@end

セレクターを作成するメソッドには単一の入力があるため、次のようにセレクターを作成します。

SEL myTestSelector = @selector(myTest:);
307
Shane Arney

@シェーン・アーニー

performSelector:withObject:withObject:

また、このメソッドは最大2つの引数を渡すためだけのものであり、遅延させることはできないことを言及したいかもしれません。 (performSelector:withObject:afterDelay:)など。

Appleが送信するオブジェクトを2つしかサポートしておらず、それをより汎用的にしなかったことは奇妙です。

13
Lirik

コードには2つの問題があります。 1つは特定されて回答されましたが、もう1つはそうではありませんでした。 1つ目は、セレクタにパラメータの名前が欠落していることです。ただし、修正した場合でも、修正されたメソッドシグネチャに複数の引数が含まれていると仮定すると、この行は例外を発生させます。修正したメソッドが次のように宣言されているとしましょう:

-(void)myTestWithString:(NSString *)sourceString comparedTo:(NSString *)testString ;

複数の引数を取るメソッドのセレクターを作成することは完全に有効です(例:@selector(myTestWithString:comparedTo :))。ただし、performSelectorメソッドでは、myTestに1つの値しか渡すことができません。myTestには、残念ながら複数のパラメーターがあります。エラーが発生し、十分な値を指定しなかったことを通知します。

メソッドは、パラメータのみであるコレクションを取得するように常に再定義できます。

-(void)myTestWithObjects:(NSDictionary *)testObjects ;

ただし、より洗練されたソリューションがあります(リファクタリングは不要です)。答えは、setArgument:atIndex:およびinvokeメソッドと共にNSInvocationを使用することです。

詳細が必要な場合は、 コード例を含む記事 を作成しました。スレッド化に焦点が当てられていますが、基本は引き続き適用されます。

がんばろう!

7
Zack

メソッドのシグネチャは意味がありませんが、タイプミスではないと確信していますか?どうやってコンパイルしているのかわかりませんが、おそらくあなたはあなたが無視しているという警告を受け取っていますか?

このメソッドは何個のパラメーターを使用すると予想しますか?

3
Rob Napier

クラスは次のように定義する必要があると考えます。

- (void) myTestWithSomeString:(NSString *) astring{
    NSLog(@"hi, %s", astring);
}

パラメーターは1つしかないため、パラメーターは1つだけにする必要があります。

NSLogで%@を使用することを検討することもできます-これは、取得するのが良い習慣です-文字列だけでなく、任意のオブジェクトを書き出します。

2
Grouchal

iOSユーザーは、自動大文字入力も期待しています。標準のテキストフィールドでは、大文字と小文字を区別する言語の文の最初の文字が自動的に大文字になります。

このような機能を実装するかどうかを決定できます。上記の機能には専用のAPIがないため、それらを提供することは競争上の優位性です。

Appleのドキュメントでは、この機能およびカスタムキーボードのその他の予想される機能に利用できるAPIはないと述べています。そのため、これを実装するには独自のロジックを見つける必要があります。

0
Kannan Prasad