Jak utworzyć „tablicę selektorów”

82

Używam iPhone SDK (3.0) i próbuję utworzyć tablicę selektorów, aby wywoływać różne metody w ramach jednej klasy.

Oczywiście robię coś źle (myślę, że @selector nie jest uważany za klasę, więc umieszczanie ich w NSArray nie działa).

Próbowałem tego, ale jest to oczywiście błędne.

Czy istnieje prosty sposób na posiadanie takiej tablicy selektorów? A może jest lepszy sposób na iterację poprzez zbiór metod?

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
źródło

Odpowiedzi:

79

Czy możesz przechowywać ciągi znaków i używać NSSelectorFromString?

Z dokumentów

NSSelectorFromString

Zwraca selektor o podanej nazwie.

SEL NSSelectorFromString (
   NSString *aSelectorName
);
blindjesse
źródło
2
Nie jest to odpowiednie rozwiązanie, gdy potrzebny jest tylko zestaw selektorów.
Aleks N.
1
NSPointerArrayjest lepiej.
DawnSong
43

To tworzy obiekt poza selektorem:

[NSValue valueWithPointer:@selector(x)]
DenNukem
źródło
2
Jak zabrałbyś się do wyodrębnienia selektora z tego, który ma być używany performSelector:?
Dean Kelly
3
@DeanKelly odpowiedział tutaj stackoverflow.com/questions/575055/ ... autor: terry franguiadakis
ABCD.ca
1
Potrzebna jest następująca obsada typuSEL x = (SEL)selectorValue.pointerValue;
DawnSong
35

Dlaczego nie użyć prostej tablicy w języku 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
źródło
3
Dobrze, ale staticnie jest tu potrzebny (inicjator nie jest stałą czasu kompilacji).
Aleks N.
12

Możesz również utworzyć tablicę NSInvocations. Jest to przydatne, jeśli potrzebujesz argumentu do wyboru.

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
Bez Morrowless
źródło
NSInvocation jest zbyt kosztowne.
DawnSong
1

Jeśli lista jest statyczna, wybrałbym rozwiązanie KennyTM, ale jeśli potrzebujesz tablicy dynamicznej lub zestawu, inną opcją, oprócz przechowywania ciągu selektora, jest utworzenie obiektu z SELwłaściwością lub ivar i zapisanie tego.

@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

Następnie możesz dodać performmetodę również do klasy i zaimplementować tam wywołanie metody.

big_m
źródło
1

Chciałbym uzupełnić dwie metody przechowywania selektorów w tablicy,

Po pierwsze, NSPointerArraymoże przechowywać nieprzezroczysty wskaźnik, taki jak SEL, jak powiedział dokument Apple ,

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

Po drugie, tablica w stylu C jest znacznie prostsza,

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

Wybierz dowolny, jak chcesz.

DawnSong
źródło