Выполнение executeSelector: для объекта, который возвращает double, а не id
Как я могу запустить произвольный селектор на объекте, возвращение которого является двойным? Например, у меня есть объект A, у которого есть метод -(double)blah;
Как я могу сделать double res = [obj performSelector:@selector(blah)];
? executeSelector возвращает id
тип объекта, так что я должен привести от id к NSInteger, чтобы удвоить - что потеряет точность?
Кроме того, я не хочу использовать объект methodSignatureForSelector
(имеется в виду, нет NSMethodSignature
и нет NSInvocation
) потому что это огромная утечка процессора во время выполнения.
3 ответа
Использует меньше всего памяти (valueForKey: использует два временных объекта), а метод msgSend не работает.
IMP myImp1 = [obj methodForSelector:@selector(getDouble)];
double aDouble1 = ((double (*) (id,SEL))myImp1)(obj,@selector(getDouble));
Вы можете взглянуть на функции времени выполнения 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
Реализуется по-разному, в зависимости от архитектуры процессора (в основном, i386 или x86_64).
Как я сказал в комментарии, эти функции реализованы с использованием ассемблера, поэтому их реализация зависит от архитектуры процессора.
В архитектуре x86_64 эта функция возвращает long double
,
Вот почему он терпит неудачу (и возвращает NAN), когда вы назначаете его 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
Если это метод без аргументов, вы можете использовать valueForKey:
а также doubleValue
на значение, возвращаемое этим методом. В противном случае, я думаю, вам придется objc_msgSend_fpret
чтобы это работало.