Ответ 1
Использовать NSValue.
Например:
NSArray* handlers = [NSArray arrayWithObjects:[NSValue valueWithPointer:handleA] ... ];
затем для доступа:
handleptr* handle = (handlerptr*)[[handlers objectAtIndex:0] pointerValue];
handle(foo_bar);
Я пытаюсь создать NSArray методов в Objective-C.
(То, что я пытаюсь выполнить здесь, в C) выглядит следующим образом:
typedef (void)(*handler)(int command);
void handleCommandA(void) { ... }
void handleCommandB(void) { ... }
static const handler handler_table[10] = {
handleCommandA, handleCommandB, handleCommandC
};
Мне нужно переносить это на Objective-C, и я не знаю, как постройте массив указателей функций (в мире Objective-C методы класса) во время компиляции.
В Objective-C у меня есть следующее.
- (void)handleCommandA { ... }
- (void)handleCommandB { ... }
/* Now how to add above 2 functions into NSArray? */
NSArray *handler_table = [NSArray arrayWithObjects:... ]; /* This doesn't seem to work. */
Использовать NSValue.
Например:
NSArray* handlers = [NSArray arrayWithObjects:[NSValue valueWithPointer:handleA] ... ];
затем для доступа:
handleptr* handle = (handlerptr*)[[handlers objectAtIndex:0] pointerValue];
handle(foo_bar);
Проблема заключается в том, что для привязки этих функций вы должны использовать ключевое слово selector, которое возвращает тип SEL. Это тип указателя, тогда как NSArray хранит объекты.
Таким образом, у вас есть три варианта:
Вторая, вероятно, лучше, и для этого вы можете использовать класс NSValue для хранения результатов селектора. Например;
NSValue* selCommandA = [NSValue valueWithPointer:@selector(handleCommandA:)];
NSValue* selCommandB = [NSValue valueWithPointer:@selector(handleCommandB:)];
NSArray *handler_table = [NSArray arrayWithObjects:selCommandA, selCommandB, nil ];
Когда вы получили правильную запись из массива, чтобы конвертировать назад, вы бы сделали:
SEL mySelector = [selCommand pointerValue];
[someObject performSelector:mySelector];
(Примечание. Я предполагаю, что из вашего синтаксиса objective-c они предназначены для использования в качестве методов для объекта, а не для глобальных функций. Если вы хотите использовать их глобально, вы должны написать их так, как вы бы С.)
Другой вариант - формализовать методы команд в протокол. Это позволяет вам писать функциональные возможности, которые будут работать на любом объекте, который реализует этот протокол, и компилятор обеспечит большую проверку, чем если бы вы просто вызывали селекторов.
например.
// some header
@protocol CommandHandler
@required
-(void) handleCommandA;
-(void) handleCommandB;
@end
// some other header
@interface someClass : NSObject<CommandHandler>
{
// you will receive compiler warnings if you do not implement the protocol functions
}
Затем обрабатывается код обработки и отправки для работы с объектами типа "CommandHandler". Например
-(void) registerForCommands:(CommandHandler*)handler
В Objective-C вы не обходите методы; вы проходите селекторами, которые в основном являются каноническими именами методов. Затем, чтобы объект ответил на сообщение селектора, вы отправляете его performSelector:
. Например:
NSString *exampleString = [NSString stringWithString:@"Hello"];
SEL methodName = @selector(stringByAppendingString:);
// ^This is the selector. Note that it just represents the name of a
// message, and doesn't specify any class or implementation
NSString *combinedString = [exampleString performSelector:methodName withObject:@" world!"];
Вы хотите создать массив NSStrings, содержащий имена интересующих вас селекторов. Для этого вы можете использовать функцию NSStringFromSelector()
. Затем, когда вы хотите их использовать, вызовите NSSelectorFromString()
в строках, чтобы вернуть исходный селектор и передать его соответствующему объекту performSelector:
. (Как показано в примере выше, приемник не закодирован в селекторе - просто имя метода - так что вам, возможно, потребуется также сохранить приемник.)