5

如何在对象上运行任意选择器,其返回是双精度值?例如,我有 obj A,它有方法 -(double)b​​lah;

我该怎么办double res = [obj performSelector:@selector(blah)];?performSelector 返回一个id类型对象,所以我应该从 id 转换为 NSInteger 到 double - 这会失去精度吗?

另外,我不想使用 obj methodSignatureForSelector(意思是 noNSMethodSignature和 no NSInvocation),因为它在运行时会消耗大量 CPU。

4

3 回答 3

8

您可能想看看 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.

另请注意,有一个 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
于 2011-11-11T00:30:57.283 回答
7

如果它是一个不带参数的方法,您可以在从该方法返回的值上使用valueForKey:doubleValue。否则,我认为你必须objc_msgSend_fpret努力让它发挥作用。

于 2011-11-11T00:30:27.050 回答
4

使用最少的内存(valueForKey:使用两个临时对象)并且 msgSend 方法不起作用。

 IMP myImp1 = [obj methodForSelector:@selector(getDouble)];
 double aDouble1 = ((double (*) (id,SEL))myImp1)(obj,@selector(getDouble));
于 2011-11-11T00:35:34.347 回答