Dav*_*vid 4 cocoa objective-c performselector
如何在对象上运行任意选择器,其返回值为double?例如,我有obj A,它有方法 - (double)blah;
我该double res = [obj performSelector:@selector(blah)];怎么办?performSelector返回一个id类型对象,所以我应该从id转换为NSInteger加倍 - 这将失去精度?
另外,我不希望使用的obj的methodSignatureForSelector(意思是,没有NSMethodSignature,没有NSInvocation),因为它是在运行时一个巨大的CPU消耗.
您可能想要查看Objective-C运行时函数,尤其是objc_msgSend_fpret.
double objc_msgSend_fpret( id self, SEL op, ... )
Run Code Online (Sandbox Code Playgroud)
它将带有浮点返回值的消息发送到类的实例.
该performSelector方法使用objc_msgSend,它返回一个id类型.
例如:
double res = objc_msgSend_fpret( obj, @selector( blah ) );
Run Code Online (Sandbox Code Playgroud)
您需要导入此objc运行时标头:
#import <objc/message.h>
Run Code Online (Sandbox Code Playgroud)
编辑
顺便说一下,这里是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.
这就是为什么当你将它分配给a时失败(并返回NAN)double.
另请注意,有一个objc_msgSend_fp2ret函数.
所以,基本上,我之前的例子不起作用:
double x = objc_msgSend_fpret( obj, @selector( blah ) );
printf( "Val: %f\n", x );
Run Code Online (Sandbox Code Playgroud)
如你所知,它将打印'NAN'.
为了使它工作,你必须这样做:
long double x = objc_msgSend_fpret( obj, @selector( blah ) );
printf( "Val: %Lf\n", x );
Run Code Online (Sandbox Code Playgroud)
这是一个有效的例子:
http://www.eosgarden.com/uploads/misc/fp.m
使用以下方法编译它:
gcc -Wall -framework Foundation -o fp fp.m
Run Code Online (Sandbox Code Playgroud)
如果它是一个没有参数的方法,则可以使用valueForKey:和doubleValue从该方法返回的值.否则,我认为你必须捣乱objc_msgSend_fpret才能使其发挥作用.
使用最少的内存(valueForKey:使用两个临时对象)并且 msgSend 方法不起作用。
IMP myImp1 = [obj methodForSelector:@selector(getDouble)];
double aDouble1 = ((double (*) (id,SEL))myImp1)(obj,@selector(getDouble));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2696 次 |
| 最近记录: |