2011-02-04 3 views
1

В настоящее время я использую objc_msgSend для вызова такого селектора при сборе объекта. Есть ли лучший способ сделать это? Вот мой код:Вызов селектора со скалярным аргументом

@protocol ADelegateProtocol { 
    -(void) timeToEventOneDidChange:(NSInterval) event1; 
    -(void) timeToEventTwoDidChange:(NSInterval) event1; 
} 

- (void) delegatesPerformSelector:(SEL) selector withTimeIntervalAsFristParameter:(NSTimeinterval) timeInterval { 
    for (id<ADelegateProtocol> delegate in delegates) { 
     if([delegate respondsToSelector:selector]) { 
      objc_msgSend(delegate, selector, timeInterval); 
     } 
    } 
} 

Селектор передается в качестве параметра, timeInterval это значение не-объект.

Примечание: я не хочу использовать KVO.

+0

Пожалуйста, измените вопрос, чтобы добавить, что селектор передается в качестве параметра.. Это имеет огромное значение. – taskinoor

+0

Я не думаю, что это действительно улучшится без изменения методов, которые вы хотите вызвать, например. 'NSInvocation' является более утомительным. –

+0

Простите меня, если я что-то упустил, но этот код предполагает, что любой селектор, переданный в этот метод, примет значение 'timeInterval' в качестве аргумента. Если вы знаете, какие аргументы будут, почему бы вам не знать, какой будет селектор? Например, может быть передан селектор 'forBar:', который принимает 'NSTimeInterval' как аргументы, но если я перейду в' fooBaz: ', который примет строку,' responsesToSelector' по-прежнему вернет true, но вы отправите временной интервал, в котором ожидается строка, и вызвать сбой ... – Jasarien

ответ

8

Если вы собираетесь использовать objc_msgSend(), вы должны должны создать корректный указатель функции типа, чтобы сделать это. Опираясь на varargs для отображения на не-varargs, не работает во всех случаях.

I.e. Вы бы хотели:

void (*myMessage)(id, SEL, NSTimeInterval) = objc_msgSend; 
myMessage(delegate, aSelector, aTimeInterval); 

(набранный в SO - рассмотреть с синтаксисом приближение :)

+0

Интересно. Не могли бы вы рассказать мне, почему код выше лучше? Я проверил обе версии и xcode производят совершенно аналогичный код сборки. –

+0

Вот только разница. Ваша версия: mov -0x14 (% ebp),% eax'; 'call *% eax', Оригинальный вызов:' call 0x13dcfe ' –

+2

Поскольку детали ABI могут меняться со временем (запрет на проблемы с двоичной совместимостью) и потому, что они могут различаться между различными архитектурами. Вы часто можете уйти, полагаясь на varargs, точно так же, как на non-varargs, но это неверно, защищать или переносить. – bbum

-1

Если делегаты являются NSArray: как насчет использования NSArray's makeObjectsPerformSelector:(SEL)aSelector.
Если вам нужно передать объект в качестве параметра, вы можете использовать makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject.

+2

Если я правильно понял вопрос, 'timeInterval' является значением, отличным от объекта, и поэтому его нельзя легко передать как' id'. – zoul

+0

Вы можете вставить его в объект, например. используя 'NSNumber'. – goetz

+2

Это не удастся, потому что приемник не отправит NSNumber, весь метод должен был быть разработан, чтобы принять NSNumber. – JustSid

1

Что вы можете использовать у objc_msgSend (что, конечно же, работает), это NSInvocation. Лично я предпочитаю способ objc_msgSend как его самый накладный бесплатный способ сделать это. Это также более быстрый способ, но это не должно иметь значения в обычном приложении (это имеет значение в играх).

Ну, выбор за вами, оба пути работают, и нет ничего плохого с objc_msgSend или NSInvocation (кроме того, что код C выглядит неправильно в методе ObjC).

Смежные вопросы