Cómo crear una "matriz de selectores"


82

Estoy usando el iPhone SDK (3.0) y estoy tratando de crear una matriz de selectores para invocar una variedad de métodos dentro de una clase.

Obviamente, estoy haciendo algo mal (creo que @selector no se considera una clase y, por lo tanto, meterlos en un NSArray no funciona).

Intenté esto, pero obviamente está mal.

¿Existe una forma sencilla de tener una matriz de selectores como esta? ¿O hay una mejor manera de iterar a través de una colección de métodos?

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;
}

Respuestas:


79

¿Podría almacenar cadenas y usar NSSelectorFromString?

De los documentos

NSSelectorFromString

Devuelve el selector con un nombre dado.

SEL NSSelectorFromString (
   NSString *aSelectorName
);

2
No es una solución adecuada para cuando solo se necesita una serie de selectores.
Aleks N.

1
NSPointerArrayes mejor.
DawnSong


35

¿Por qué no usar simplemente una matriz C simple?

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

...

for (int i = 0; i < sizeof(selectors)/sizeof(selectors[0]); i++) {
  [self performSelector:selectors[i]];
  // ....
}

3
Bien, pero staticno es necesario aquí (el inicializador no es una constante en tiempo de compilación).
Aleks N.

12

También puede crear una matriz de NSInvocations. Esto es útil si necesita un argumento que vaya con su selector.

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

NSInvocation es demasiado caro.
DawnSong

1

Si la lista es estática, optaría por la solución de KennyTM, pero si necesita una matriz o un conjunto dinámico, otra opción, además de almacenar la cadena de selección, es crear un objeto con una SELpropiedad o ivar y almacenarlo.

@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

A continuación, también puede agregar un performmétodo a la clase e implementar la llamada al método allí.


1

Me gustaría complementar dos métodos para almacenar selectores en una matriz,

Primero, NSPointerArraypuede almacenar un puntero opaco, como SEL, como dijo Apple doc ,

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

En segundo lugar, la matriz de estilo C es mucho más simple,

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

Elija cualquiera que desee.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.