objective-c - 执行选择器转换

标签 objective-c reflection casting performselector

在 performSelector 的结果上进行 float/double/CGFloat 转换时会出现一个非常奇怪的行为:

为什么会这样?

BOOL property = (BOOL)[self.object performSelector:@selector(boolProperty)];
NSInteger property = (NSInteger) [self.object performSelector:@selector(integerProperty)];

这不是

CGFloat property = (CGFloat) [self.object performSelector:@selector(floatProperty)];

起初我尝试这样做:

CGFloat property = [[self.object performSelector:@selector(floatProperty)] floatValue];

但我最终遇到了 EXC_BAD_ACCESS 运行时错误。我已经想出了解决这个问题的方法,但我想了解为什么它适用于 Integer 和 Bool 而不是浮点类型。

我的技巧:

@implementation NSObject (AddOn)
-(CGFloat)performFloatSelector:(SEL)aSelector
{
  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:aSelector]];
  [invocation setSelector:aSelector];
  [invocation setTarget:self];
  [invocation invoke];
  CGFloat f = 0.0f;
  [invocation getReturnValue:&f];
  return f;
}
@end

然后:

CGFloat property = [self.object performFloatSelector:@selector(floatProperty)];

最佳答案

performSelector 方法仅支持不返回任何内容或返回对象的方法。这在其文档中有说明:

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

您的“hack”只是调用返回非对象的选择器的正确方法。

它似乎适用于整数和 bool 方法的原因是与方法返回值的方式有关。 performSelector的返回类型是id,一个对象指针类型。类整数值;其中包括 NSIntegerBOOL 和对象指针;通常在通用寄存器中返回,但是浮点值通常在浮点寄存器中返回。编译器将始终从用于返回 id 值的寄存器加载结果,然后执行转换所需的任何操作。对于整数和 bool 值,加载的值可能是正确的,并且在这些情况下转换是空操作,因此一切(似乎)都有效。对于浮点值,加载的值不正确 - 它不是被调用方法返回的值,因为它位于不同的寄存器中。

请注意,使用 performSelector 调用非对象、非 void 选择器可能会导致 ARC 下的内存问题——如果是这种情况,编译器通常会发出警告。

调用选择器的 NSInvocation 方法适用于非对象返回类型,因为它的参数之一是方法签名本身。使用签名 NSInvocation 能够确定返回值的类型和返回方式,从而正确地返回给调用者。

HTH

关于objective-c - 执行选择器转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23902132/

相关文章:

c - 函数参数匿名结构

ios - 在 objective-c 中更改电话号码的颜色(UITextView ...在 xib 文件中启用检测电话号码)

java - 如何通过阅读代码确定 Java 源代码的所有运行时(但不是静态)依赖项?

go - 如何在 golang 中列出包的公共(public)方法

sql - 将 INT 转换为 DATETIME (SQL)

sql - CAST 错误地将 float 转换为 varchar

iOS 应用内购买验证

ios - 如何在 objective-c 中禁用以编程方式创建的 UIBarButtonItem?

objective-c - UIImageView 中的 JPG 图像内存占用

java java.lang.reflect.Array.getLength 与 array.length