Как создать «массив селекторов»

82

Я использую iPhone SDK (3.0) и пытаюсь создать массив селекторов для вызова различных методов в одном классе.

Очевидно, я делаю что-то не так (я думаю, что @selector не считается классом, и поэтому вставка их в NSArray не работает).

Я пробовал это, но это явно неправильно.

Есть ли простой способ получить такой массив селекторов? Или есть лучший способ перебрать набор методов?

selectors = [NSArray arrayWithObjects:
                          @selector(method1),
                          @selector(method2),
                          @selector(method3),
                          @selector(method4),
                          @selector(method5),
                          @selector(method6),
                          @selector(method7), nil];

for (int i = 0; i < [selectors count]; i++) {
    if ([self performSelector:[selectors objectAtIndex:i]]) // do stuff;
}
user141146
источник

Ответы:

79

Не могли бы вы хранить строки и использовать NSSelectorFromString?

Из документов

NSSelectorFromString

Возвращает селектор с заданным именем.

SEL NSSelectorFromString (
   NSString *aSelectorName
);
Blindjesse
источник
2
Не подходящее решение, когда нужен только массив селекторов.
Алекс Н.
1
NSPointerArrayлучше.
DawnSong
43

Это создает объект вне селектора:

[NSValue valueWithPointer:@selector(x)]
DenNukem
источник
2
Как бы вы извлекли из него селектор для использования performSelector:?
Дин Келли
3
@DeanKelly ответил здесь stackoverflow.com/questions/575055/… Терри Франгуадакис
ABCD.ca
1
SEL x = (SEL)selectorValue.pointerValue;
Требуется
35

Почему бы просто не использовать простой массив C?

static const SEL selectors[] = {@selector(method1),
                                ....
                                @selector(method7)};

...

for (int i = 0; i < sizeof(selectors)/sizeof(selectors[0]); i++) {
  [self performSelector:selectors[i]];
  // ....
}
Kennytm
источник
3
Хорошо, но staticздесь не требуется (инициализатор не является константой времени компиляции).
Алекс Н.
12

Вы также можете создать массив NSInvocations. Это удобно, если вам нужен аргумент для вашего селектора.

NSMethodSignature *sig = [[yourTarget class] instanceMethodSignatureForSelector:yourSEL];
NSInvocation *inv = [NSInvocation invocationWithMethodSignature:sig];
[inv setTarget:yourTarget];
[inv setSelector:yourSEL];
[inv setArgument:&yourObject atIndex:2]; // Address of your object
Morrowless
источник
NSInvocation слишком дорого.
DawnSong
1

Если список статический, я бы выбрал решение Kenny TM, но если вам нужен динамический массив или набор, другой вариант, помимо сохранения строки селектора, - создать объект со SELсвойством или ivar и сохранить его.

@interface SelectorObject : NSObject
@property (assign, readonly, nonatomic) SEL selector;
- (id)initWithSelector:(SEL)selector;
@end

@implementation SelectorObject
- (id)initWithSelector:(SEL)selector {
  self = [super init];
  if (self) {
    _selector = selector;
  }
  return self;
}
@end

Затем вы также можете добавить performметод в класс и реализовать там вызов метода.

big_m
источник
1

Хочу дополнить два метода хранения селекторов в массиве,

Во-первых, NSPointerArrayможет хранить непрозрачный указатель, например SEL, как сказал документ Apple ,

NSPointerArray *selectors = [[NSPointerArray alloc] initWithOptions: NSPointerFunctionsOpaqueMemory];
[selectors addPointer:@selector(onSendButton:)];
[button addTarget: self action:[selectors pointerAt:0] forControlEvents:UIControlEventTouchUpInside];

Во-вторых, массив в стиле C намного проще,

SEL selectors[] = { @selector(onSendButton:) };
[button addTarget: self action:selectors[0] forControlEvents:UIControlEventTouchUpInside];

Выбирайте любую на свой вкус.

РассветПесня
источник