So erstellen Sie ein "Array von Selektoren"

82

Ich verwende das iPhone SDK (3.0) und versuche, ein Array von Selektoren zu erstellen , um eine Vielzahl von Methoden innerhalb einer Klasse aufzurufen.

Offensichtlich mache ich etwas falsch (ich denke, @selector wird nicht als Klasse angesehen und daher funktioniert es nicht, sie in ein NSArray zu stopfen).

Ich habe es versucht, aber es ist offensichtlich falsch.

Gibt es eine einfache Möglichkeit, eine Reihe solcher Selektoren zu haben? Oder gibt es eine bessere Möglichkeit, eine Sammlung von Methoden zu durchlaufen?

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
quelle

Antworten:

79

Könnten Sie Zeichenfolgen speichern und NSSelectorFromString verwenden?

Aus den Dokumenten

NSSelectorFromString

Gibt den Selektor mit einem bestimmten Namen zurück.

SEL NSSelectorFromString (
   NSString *aSelectorName
);
blindjesse
quelle
2
Keine geeignete Lösung, wenn nur ein Array von Selektoren benötigt wird.
Aleks N.
1
NSPointerArrayist besser.
DawnSong
43

Dadurch wird ein Objekt außerhalb des Selektors erstellt:

[NSValue valueWithPointer:@selector(x)]
DenNukem
quelle
2
Wie würden Sie den Selektor daraus extrahieren, der von verwendet werden soll performSelector:?
Dean Kelly
3
@ DeanKelly antwortete hier stackoverflow.com/questions/575055/… von Terry Franguiadakis
ABCD.ca
1
Typ Besetzung wird wie folgt benötigt,SEL x = (SEL)selectorValue.pointerValue;
DawnSong
35

Warum nicht einfach ein einfaches C-Array verwenden?

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

...

for (int i = 0; i < sizeof(selectors)/sizeof(selectors[0]); i++) {
  [self performSelector:selectors[i]];
  // ....
}
kennytm
quelle
3
Gut, staticwird hier aber nicht benötigt (Initialisierer ist keine Konstante zur Kompilierungszeit).
Aleks N.
12

Sie können auch ein Array von NSInvocations erstellen . Dies ist praktisch, wenn Sie ein Argument für Ihre Auswahl benötigen.

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
Morgenlos
quelle
NSInvocation ist zu teuer.
DawnSong
1

Wenn die Liste statisch ist, würde ich mich für die KennyTM-Lösung entscheiden. Wenn Sie jedoch ein dynamisches Array oder Set benötigen, besteht eine andere Option neben dem Speichern der SELAuswahlzeichenfolge darin, ein Objekt mit einer Eigenschaft oder einem ivar zu erstellen und dieses zu speichern.

@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

Sie können dann auch performder Klasse eine Methode hinzufügen und dort den Methodenaufruf implementieren.

big_m
quelle
1

Ich möchte zwei Methoden zum Speichern von Selektoren in einem Array ergänzen:

Erstens NSPointerArraykann undurchsichtiger Zeiger gespeichert werden, wie SEL, wie Apple Doc sagte,

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

Zweitens ist das Array im C-Stil viel einfacher.

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

Wählen Sie eine nach Ihren Wünschen.

DawnSong
quelle