Выполнение 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 чтобы это работало.

Другие вопросы по тегам