Как создать NSArray (или NSMutableArray) методов класса в Objective-C?


14

Я пытаюсь построить NSArray методов в Objective-C.

(То, что я пытаюсь достичь здесь что-то вроде следующего в C)

Я должен порт это Objective-C, и я не знаю, как построить массив (в Objective-c world, методах класса) во время компиляции.

В 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. */ 
5

Использование NSValue.

Например:

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

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

handleptr* handle = (handlerptr*)[[handlers objectAtIndex:0] pointerValue]; 
handle(foo_bar); 

28

Проблема заключается в том, что для связывания этих функций вы должны использовать ключевое слово селектора, которое возвращает тип 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]; 

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

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

E.g.

// 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 
  0

Я предпочитаю использовать строки вместо указателей, как это сделало бы отладку гораздо проще. Посмотрите на NSStringFromSelector() и NSSelectorFromString(). 17 май. 092009-05-17 09:10:39

+1

Небольшая коррекция с использованием селектора на самом деле выглядит следующим образом: [someObject performSelector: mySelector]; 19 янв. 112011-01-19 03:30:33


4

В 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:.(Как показано в примере выше, приемник не закодирован в селекторе - просто имя метода - так что вам, возможно, потребуется также сохранить приемник.)