Как построить NSArray (или NSMutableArray) методов класса в Objective-C? - PullRequest
14 голосов
/ 22 февраля 2009

Я пытаюсь создать 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. */

Ответы [ 3 ]

29 голосов
/ 22 февраля 2009

Проблема здесь в том, что для связывания этих функций вы должны использовать ключевое слово selector, которое возвращает тип SEL. Это тип указателя, тогда как NSArray хранит объекты.

Таким образом, у вас есть три варианта;

  1. Использовать обычный массив типа C
  2. Сложите функции в производный класс NSObject, который будет их вызывать.
  3. Использовать протокол.

Второе, вероятно, лучше, и для этого вы можете использовать класс 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];

(Заметьте, я предполагаю, что из вашего синтаксиса target-c предполагается, что они предназначены для использования в качестве методов объекта, а не глобальных функций. Если вы хотите использовать их глобально, вы должны написать их так, как если бы они были простыми C).

Другой вариант - формализовать командные методы в протокол. Это позволяет вам написать функциональность, которая будет работать с любым объектом, который реализует этот протокол, а компилятор обеспечит больше проверок, чем если бы вы просто вызывали селекторы.

* 1023 Е.Г. *

// 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». * 1026 например *

-(void) registerForCommands:(CommandHandler*)handler
6 голосов
/ 30 апреля 2009

Использовать NSValue.

Например:

NSArray* handlers = [NSArray arrayWithObjects:[NSValue valueWithPointer:handleA] ... ];

затем для доступа:

handleptr* handle = (handlerptr*)[[handlers objectAtIndex:0] pointerValue];
handle(foo_bar);
4 голосов
/ 22 февраля 2009

В 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!"];

Вам нужно создать массив строк NSS, содержащих имена интересующих вас селекторов. Для этого вы можете использовать функцию NSStringFromSelector(). Затем, когда вы захотите их использовать, вызовите NSSelectorFromString() для строк, чтобы вернуть исходный селектор и передать его соответствующему объекту performSelector:. (Как показано в примере выше, получатель не закодирован в селекторе - только имя метода - поэтому вам может потребоваться также сохранить получатель.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...