如何在对象上运行任意选择器,其返回值为double?例如,我有obj A,它有方法 - (double)blah;
我该怎样做double res = [obj performSelector:@selector(blah)];
? performSelector返回一个id
类型的对象,所以我应该从id转换为NSInteger加倍 - 这将失去精度?
另外,我不想要使用obj的methodSignatureForSelector
(意思是,没有NSMethodSignature
而没有NSInvocation
),因为它是运行时CPU流量很大。
答案 0 :(得分:7)
您可能需要查看Objective-C运行时函数,尤其是objc_msgSend_fpret
。
double objc_msgSend_fpret( id self, SEL op, ... )
它将带有浮点返回值的消息发送到类的实例。
performSelector
方法使用objc_msgSend
,返回id
类型。
例如:
double res = objc_msgSend_fpret( obj, @selector( blah ) );
您需要导入此objc运行时标头:
#import <objc/message.h>
修改强>
顺便说一句,这是ObjC运行时引用的链接: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
编辑2 - 重要
objc_msgSend_fpret
以不同的方式实现,具体取决于CPU架构(基本上是i386或x86_64)。
正如我在评论中所说,这些功能是使用汇编实现的,因此它们的实现取决于CPU架构。
在x86_64架构下,此函数返回long double
。
这就是当你将它分配给double
时失败(并返回NAN)的原因。
另请注意,有一个objc_msgSend_fp2ret函数。
所以,基本上,我之前的例子不起作用:
double x = objc_msgSend_fpret( obj, @selector( blah ) );
printf( "Val: %f\n", x );
正如您所注意到的,它将打印'NAN'。
为了使其有效,你必须这样做:
long double x = objc_msgSend_fpret( obj, @selector( blah ) );
printf( "Val: %Lf\n", x );
这是一个有效的例子:
http://www.eosgarden.com/uploads/misc/fp.m
使用以下方式编译:
gcc -Wall -framework Foundation -o fp fp.m
答案 1 :(得分:6)
如果它是一个没有参数的方法,则可以对该方法返回的值使用valueForKey:
和doubleValue
。否则,我认为你必须使用objc_msgSend_fpret
进行捣乱才能使其正常工作。
答案 2 :(得分:3)
使用最少内存(valueForKey:使用两个临时对象),msgSend方法不起作用。
IMP myImp1 = [obj methodForSelector:@selector(getDouble)];
double aDouble1 = ((double (*) (id,SEL))myImp1)(obj,@selector(getDouble));