web-dev-qa-db-ja.com

@selectorの引数

セレクターで引数を渡す方法はありますか?

例:この方法があります

- (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{

}

2つの引数を渡すセレクターを介してこの関数を呼び出す必要があります。

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(/*my method*/) userInfo:nil repeats:YES];

これどうやってするの?

35
isiaatz

NSTimerメソッドを使用できます:

_+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds
                                 invocation:(NSInvocation *)invocation
                                    repeats:(BOOL)repeats;
_

代わりに、NSInvocationオブジェクトを使用すると、引数を渡すことができます。 NSInvocationオブジェクトは docs として定義されています:

静的にレンダリングされたObjective-Cメッセージ。つまり、オブジェクトに変換されるアクションです。

セレクターを使用してNSTimerオブジェクトを作成する場合、次のメソッドの形式が必要です。

_- (void)timerFireMethod:(NSTimer*)theTimer
_

NSInvocationを使用すると、ターゲット、セレクター、および渡す引数を設定できます。

_SEL selector = @selector(myMethod:setValue2:);

NSMethodSignature *signature = [MyObject instanceMethodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:selector];

NSString *str1 = @"someString";
NSString *str2 = @"someOtherString";

//The invocation object must retain its arguments
[str1 retain];
[str2 retain];

//Set the arguments
[invocation setTarget:targetInstance];
[invocation setArgument:&str1 atIndex:2];
[invocation setArgument:&str2 atIndex:3];

[NSTimer scheduledTimerWithTimeInterval:0.1 invocation:invocation repeats:YES];
_

ここで、MyObjectは、_myMethod:setValue2:_が宣言および実装されているクラスです。_instanceMethodSignatureForSelector:_は、NSObjectに対して宣言されたNSMethodSignatureオブジェクトを返す便利な関数ですあなた、NSInvocationに渡されます。

また、_setArgument:atIndex:_では、セレクターとして設定されたメソッドに渡される引数のインデックスは、インデックス2から始まります。ドキュメントから:

インデックス0および1は、それぞれ非表示の引数selfおよび_cmdを示します。これらの値は、setTarget:およびsetSelector:メソッドを使用して直接設定する必要があります。通常メッセージで渡される引数には、インデックス2以上を使用してください。

56
Alex Rozanski

scheduledTimerWithTimeInterval:の場合、渡すセレクターに指定できる引数は1つだけです。さらに、その1つの引数はNSTimer *オブジェクトでなければなりません。つまり、セレクターは次の形式をとる必要があります。

- (void)timerFireMethod:(NSTimer*)theTimer

あなたができることはuserInfo辞書に引数を保存し、タイマーコールバックから必要なセレクターを呼び出すことです:

- (void)startMyTimer {
    /* ... Some stuff ... */
    [NSTimer scheduledTimerWithTimeInterval:0.1 
                                     target:self 
                                   selector:@selector(callMyMethod:) 
                                   userInfo:[NSDictionary dictionaryWithObjectsAndKeys:someValue, 
                       @"value1", someOtherValue, @"value2", nil] 
                                    repeats:YES];
}

- (void)callMyMethod:(NSTimer *)theTimer {
    NSString *value1 = [[theTimer userInfo] objectForKey:@"value1"];
    NSString *value2 = [[theTimer userInfo] objectForKey:@"value2"];
    [self myMethod:value1 setValue2:value2];
}
27
Matt Ball

ブロックの仕事のように見えます(これはSnow Leopardを対象としていると想定しています)。

-jcr

2
NSResponder

ブロックは今や明らかな答えのように見えます...しかし、クラシックランタイムでは非常にありふれた別のイディオムがあり、単一のオブジェクトで引数をピクルします。

 - (void)doMyMethod:(NSDictionary *)userInfo
 {
     [self myMethod: [userInfo objectForKey:@"value1"] setValue2: [userInfo objectForKey:@"value2"]];
 }
 - (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{

}

今、あなたはに派遣することができます

[self performSelector:@selector(doMyMethod:) withObject:@{@"value1":@"value1",@"value2":@"value2"}];
0
Grady Player