2009-05-31 23 views
51

Para el método:¿Cómo paso @selector como parámetro?

[NSThread detachNewThreadSelector:@selector(method:) toTarget:self withObject:(id)SELECTOR]; 

¿Cómo se pasan en un @selector? Intenté convertirlo en (id) para hacer que se compilara, pero se bloquea en tiempo de ejecución.


Más específicamente, tengo un método como este:

+(void)method1:(SEL)selector{ 
[NSThread detachNewThreadSelector:@selector(method2:) toTarget:self withObject:selector]; 
} 

Se estrella. ¿Cómo paso el selector sin colgar, para que el nuevo hilo pueda llamar al selector cuando el hilo está listo?

Respuesta

67

El problema aquí no está pasando un selector a un método, per se, sino que pasa a un selector donde se espera un objeto. Para pasar un valor no objeto como un objeto, puede usar NSValue. En este caso, deberá crear un método que acepte un NSValue y recupere el selector apropiado. Aquí está un ejemplo de implementación:

@implementation Thing 
- (void)method:(SEL)selector { 
    // Do something 
} 

- (void)methodWithSelectorValue:(NSValue *)value { 
    SEL selector; 

    // Guard against buffer overflow 
    if (strcmp([value objCType], @encode(SEL)) == 0) { 
     [value getValue:&selector]; 
     [self method:selector]; 
    } 
} 

- (void)otherMethodShownInYourExample { 
    SEL selector = @selector(something); 
    NSValue *selectorAsValue = [NSValue valueWithBytes:&selector objCType:@encode(SEL)]; 
    [NSThread detachNewThreadSelector:@selector(methodWithSelectorValue:) toTarget:self withObject:selectorAsValue]; 
} 
@end 
+0

+50 ¡Excelente! Nunca recuerdo cómo hacer esto ... – bentford

+0

¿Por qué tienes que hacer eso con el nuevo hilo? – cstack

+2

@cstack: Si miras la pregunta, generar un nuevo hilo es lo que OP intentaba hacer. Entonces usé la misma tarea en mi ejemplo. Pero esta técnica no es de ninguna manera específica para engendrar un nuevo hilo. – Chuck

0

Si no desea especificar un objeto sólo tiene que utilizar nula.

[NSThread detachNewThreadSelector:@selector(method:) toTarget:self withObject:nil]; 

Si necesita pasar un objeto al selector se vería algo como esto.

Aquí estoy pasando una cadena al método "setText".

NSString *string = @"hello world!"; 
[NSThread detachNewThreadSelector:@selector(setText:) toTarget:self withObject:string]; 


-(void)setText:(NSString *)string { 
    [UITextField setText:string]; 
} 
+0

por favor vea las preguntas actualizadas. ¡Gracias! – erotsppa

4

Uso NSValue, así:

+(void)method1:(SEL)selector { 
    NSValue *selectorValue = [NSValue value:&selector withObjCType:@encode(SEL)]; 
    [NSThread detachNewThreadSelector:@selector(method2:) 
          toTarget:self 
          withObject:selectorValue]; 
} 

NSValue pretende ser un objeto-contenedor para tipos que no son objeto arbitrario.

+0

Creo que falta un signo "&" antes del "selector" para que termine siendo "... valor: & selector ..." en lugar de "... valor: selector ...". – Senseful

+0

Es cierto. Gracias por notarlo; Lo he arreglado –

41

Puede convertir selectores y objetos de cadena utilizando las funciones NSStringFromSelector() y NSSelectorFromString(). Así que puedes pasar objetos de cadena en su lugar.

Alternativamente, si no desea cambiar sus métodos, puede crear un NSInvocation para crear una invocación para su llamada a método (ya que puede configurar invocaciones con argumentos no objeto), y luego llamarlo a hacer [NSThread detachNewThreadSelector:@selector(invoke) toTarget:myInvocation withObject:nil];

+0

Esto necesita más votos positivos –

+0

Esta es la mejor respuesta del lote, desearía poder hacer que más personas voten más que este. –

+0

Muchas gracias, esto era justo lo que necesitaba. – amergin

Cuestiones relacionadas