2010-02-19 21 views
25

He estado usando @selector hoy por primera vez y no he podido averiguar cómo hacer lo siguiente? ¿Cómo escribirías el @selector si tuvieras más de un argumento?@selector - ¿Con múltiples argumentos?

No hay argumentos:

-(void)printText { 
    NSLog(@"Fish"); 
} 

[self performSelector:@selector(printText) withObject:nil afterDelay:0.25]; 

argumento individual:

-(void)printText:(NSString *)myText { 
    NSLog(@"Text = %@", myText); 
} 

[self performSelector:@selector(printText:) withObject:@"Cake" afterDelay:0.25]; 

dos argumentos:

-(void)printText:(NSString *)myText andMore:(NSString *)extraText { 
    NSLog(@"Text = %@ and %@", myText, extraText); 
} 

[self performSelector:@selector(printText:andMore:) withObject:@"Cake" withObject:@"Chips"]; 

múltiples argumentos: (es decir, más de 2)

NSInvocation

+0

Se ha actualizado para reflejar las respuestas, gracias por toda la ayuda, muy apreciados. – fuzzygoat

+1

sus "argumentos dobles" no tienen un retraso – user102008

Respuesta

35

 

- (id)performSelector:(SEL)aSelector 
      withObject:(id)anObject 
      withObject:(id)anotherObject 

Desde el Documentation:

Este método es el mismo que performSelector: excepción de que puede suministrar dos argumentos para aSelector. aSelector debe identificar un método que puede tomar dos argumentos de tipo id. Para los métodos con otros tipos de argumentos y valores devueltos, use NSInvocation.

por lo que en su caso se debería utilizar:

[self performSelector:@selector(printText:andMore:) 
      withObject:@"Cake" 
      withObject:@"More Cake"] 
5
@selector(printText:andMore:) 
+4

gracias, pero ¿cómo podría especificar los argumentos @ "Pastel" y @ "Más pastel"? – fuzzygoat

4
[self performSelector:@selector(printText:andMore) withObject:@"Cake" withObject:@"More Cake"]; 
+1

Hay '-performSelector: withObject: withObject:' y '-performSelector: withObject: afterDelay:', pero la mezcla de los dos no existe. – kennytm

+0

Tienes razón. Estaba copiando/pegando y cometí un error. Buen lugar – pheelicks

1

Como KennyTM señaló, la sintaxis del selector es

@selector(printText:andMore:) 

Usted lo llama con

performSelector:withObject:withObject. 

.. . Si necesita más argumentos o diferentes tipos, necesita usar NSIvocation

14

Tuve un problema en el que necesitaba usar el afterDelay junto con varios argumentos para mi método @selector. ¿Solución? Use una función de envoltura

decir que esta es la función que quiero pasar a @selector:

-(void)myFunct:(NSString *)arg1 andArg:(NSString *)arg2 andYetAnotherArg:(NSString *)arg3; 

Obviamente, no puedo incluso utilizar withObject: withObject: aquí, así, hacer un envoltorio!

-(void)myFunctWrapper:(NSArray *)myArgs { 
    [self myFunct:[myArgs objectAtIndex:0] andArg:[myArgs objectAtIndex:1] andYetAnotherArg:[myArgs objectAtIndex:2]]; 
} 

y utilizarlo haciendo:

NSArray *argArray = [NSArray arrayWithObjects:string1,string2,string3,nil]; 
[self performSelector:@selector(myFunctWrapper:) withObject:argArray afterDelay:1.0]; 

De esta manera puedo tener varios argumentos y utilizar el selector con retraso.

+1

Esas cosas que llamas funciones en realidad se llaman métodos. No solo en Objective-C, sino en todos los lenguajes de programación serios se hace esta distinción. Para ser precisos: tan pronto como esta cosa se adjunta a un objeto, es un método. De pie solo se llama una función. – Jacque

+0

Gracias por la información? – aqua

+0

Para el caso general, suelo usar un diccionario para pasar los parms. No depende de la orden y puede tener fácilmente parms opcionales, etc. –

17

Como una alternativa para NSInvocation cuando se tiene más de dos parámetros, puede utilizar de -methodForSelector: como en el siguiente ejemplo NSObject:

SEL a_selector = ... 
Type1 obj1 = ... 
Type2 obj2 = ... 
Type3 obj3 = ... 
typedef void (*MethodType)(id, SEL, Type1, Type2, Type3); 
MethodType methodToCall; 
methodToCall = (MethodType)[target methodForSelector:a_selector]; 
methodToCall(target, a_selector, obj1, obj_of_type2, obj_of_type3); 
+1

Esto es exactamente lo que estaba buscando. Necesitaba poder pasar los parámetros por referencia, y no pude encontrar la forma de hacerlo con performSelector. Lo descubrí con NSInvocation, pero seguí recibiendo errores malloc. Esto hizo exactamente lo que necesitaba que hiciera. –

2

Abundando en Ben-Uri's answer, que puede escribirse camino más corto.

E.g. llamar al método UIView- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view puede hacerse de la siguiente manera:

SEL selector = @selector(covertPoint:toView:); 
IMP method = [viewA methodForSelector:selector]; 
CGPoint pointInB = method(viewA, selector, pointInA, viewB); 
+0

Basado en esta publicación SO (http://stackoverflow.com/questions/10952996/why-does-this-code-give-exc-bad-access-using-imp) tendrá problemas de memoria de esta manera si tiene ARC habilitado – stuckj

4

Otra opción es utilizar una sintaxis aún más corto:

#import <objc/message.h> // objc_msgSend 
... 
((void (*)(id, SEL, Type1, Type2, Type3))objc_msgSend)(target, a_selector, obj1, obj_of_type2, obj_of_type3); 
Cuestiones relacionadas