web-dev-qa-db-ja.com

performSelectorの戻り値:

PerformSelectorの戻り値は何ですか。NSDateComponentsの 'week'(intを返す)など、(オブジェクトの)プリミティブ型を返すセレクターを渡した場合はどうなりますか?

37
cfischer

NSInvocationを使用して浮動小数点数を返す例:

SEL selector = NSSelectorFromString(@"someSelector");
if ([someInstance respondsToSelector:selector]) {
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                                [[someInstance class] instanceMethodSignatureForSelector:selector]];
    [invocation setSelector:selector];
    [invocation setTarget:someInstance];
    [invocation invoke];
    float returnValue;
    [invocation getReturnValue:&returnValue];
    NSLog(@"Returned %f", returnValue);
}
80
dizy

私は、performSelectorから戻り値を取得できないと思います。 NSInvocationを調べてください。

9
dasdom

昔の質問に対する新しい答え〜

performSelectorから戻り値を取得するより簡潔な方法があります

NSInvocationOperation *invo = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(height) object:nil];
[invo start];
CGFloat f = 0;
[invo.result getValue:&f];
NSLog(@"operation: %@", @(f));

その中で

- (CGFloat)height {
    return 42;
}

出力

2017-03-28 16:22:22.378 redpacket[46656:7361082] operation: 42

5
dopcn

質問の2番目の部分に答えるために、プリミティブを返すセレクターを呼び出す別の方法は、次のように関数ポインターを取得して呼び出すことです(someSelectorは浮動小数点数を返し、引数がないと仮定します)。

SEL selector = NSSelectorFromString(@"someSelector");
float (*func)(id,SEL) = (float (*)(id,SEL))[someInstance methodForSelector: selector];
printf("return value is: %f", (func)(someInstance, selector));
3
joshbodily

Dizyの提案どおりに実装されたNSInvocationを試しましたが、期待どおりに機能しました。

私はまた別の方法、つまり.

int result = objc_msgSend([someArray objectAtIndex:0], @selector(currentPoint));

上記の場合、ブログに記載されているように、コンパイラーをバイパスしてobjc_msgSend呼び出しを明示的に挿入しています。 http://www.cocoawithlove.com/2011/06/big-weakness-of-objective-c-weak -typing.html

この場合、次の警告が表示されました:ライブラリ関数 'objc_msgSend'をタイプ 'id(id、SEL、...)'で暗黙的に宣言していますライブラリ関数を直接呼び出しているため、明らかです。

だから、私はNSInvocationを使って実装しましたが、これは完全にうまく機能しています。

2
Anni S