如何返回像-performSelector这样的任何类型的值?

时间:2014-07-16 11:15:52

标签: objective-c

-performSelector方法的返回类型为id,我在Apple文档中发现了这一点:

For methods that return anything other than an object, use NSInvocation.

但以下代码效果很好:

BOOL boolValue = (BOOL)[self performSelector:@selector(boolValue)];

它可以返回idBOOLNSInteger等。我想知道该怎么做?因为投了BOOL或者在return语句中NSIntegerid导致错误:

Cast of 'NSInteger' (aka 'long') to 'id' is disallowed with ARC

提前致谢!

----编辑----

感谢您的回答。

我知道这样做并不好,我也知道如何使用NSInvocation,我只是想知道-performSelector方法是如何实现的。

4 个答案:

答案 0 :(得分:4)

除了在其他答案中使用NSInvocation之外,如果您在编译时知道类型,也可以直接调用实现函数。

SEL sel = @selector(boolValue);
IMP imp = [self methodForSelector:sel];
BOOL value = ((BOOL (*)(id, SEL))imp)(self, sel);

你必须将imp转换为正确的类型,否则它是未定义的行为并且如果你幸运的话会崩溃。

答案 1 :(得分:2)

获取返回值的最佳方法是使用NSInvocation而不是执行选择器。以下是example: -

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);
}

答案 2 :(得分:1)

首先,您的代码不起作用:要查看它是如何被破坏的,请在64位系统上运行它。在32位系统上,它通过一次不幸的事故but on 64-bit systems the upper half of the returned value will contain garbage data运行。这是因为BOOL会在将结果返回给您之前强制转换为id,这会导致未定义的行为。

要做得对,请查看Stack Overflow上的众多答案之一 - 例如,this one

答案 3 :(得分:0)

您编写的代码仅适用于您滥用类型。选择器boolValue返回的BOOL被强制转换为id,然后返回BOOL。这是有风险的,因为id字段的长度不能保证与BOOL的长度相同。

ARC对id返回类型进行了额外的处理,因此这种滥用行为根本不起作用,这就是你得到编译错误的原因。有一个桥接黑客可以使它工作,但我在这里重复它,因为它完全没有必要,将导致真正糟糕的代码。

有关正确执行此操作的详细信息,请参阅此问题:iPhone: performSelector with BOOL parameter?