2008-09-22 19 views
89

Sé cómo crear un SEL en tiempo de compilación usando @selector(MyMethodName:), pero lo que quiero hacer es crear un selector dinámicamente desde NSString. ¿Esto es posible?¿Cómo puedo crear dinámicamente un selector en tiempo de ejecución con Objective-C?

Lo que puedo hacer:

SEL selector = @selector(doWork:); 
[myobj respondsToSelector:selector]; 

Lo que quiero hacer: (pseudo código, esto obviamente no funciona)

SEL selector = selectorFromString(@"doWork"); 
[myobj respondsToSelector:selector]; 

He estado buscando en los documentos de la API de Apple, pero no he encontrado una manera que no se base en la sintaxis @selector(myTarget:) en tiempo de compilación.

Respuesta

175

No soy un programador de Objective-C, simplemente un simpatizante, pero tal vez NSSelectorFromString es lo que necesita. Se menciona explícitamente en el Runtime Reference que puede usarlo para convertir una cadena en un selector.

+5

tengo que poner al día mi Google-fu. eso es exactamente lo que estaba buscando (o no lo estaba). – craigb

+0

Bueno, todavía tenía los enlaces volando en mis marcadores desde que he leído a través de la Objective-C 2.0 docs hace un par de días. –

40

De acuerdo con la documentación de XCode, su psuedocode básicamente lo hace bien.

Es más eficiente asignar valores a las variables SEL en tiempo de compilación con la directiva @selector(). Sin embargo, en algunos casos, un programa puede necesitar convertir una cadena de caracteres a un selector en tiempo de ejecución. Esto se puede hacer con la función NSSelectorFromString:

setWidthHeight = NSSelectorFromString(aBuffer);

Editar: Charlatán, demasiado lento. : P

+2

'NSStringFromSelector (@" doWork ")' lo convierte a la inversa (solo fyi) – bendytree

+8

Creo que quiere decir, NSStringFromSelector (@selector (doWork)) – jpswain

+0

¿Y qué hace ese selector supuestamente? ¿No deberíamos especificar un bloque o algo así? –

8

Tendría que decir que que es un poco más complicado de lo respuestas de los encuestados anteriores podrían sugerir ... si de hecho realmente desea crear un selector ... no sólo "llamar a uno "que 'tiene por ahí' ...

lo necesario para crear un puntero de función que será llamada por el 'nuevo método' .. así que para un método como [self theMethod:(id)methodArg];, que iba a escribir ...

void (^impBlock)(id,id) = ^(id _self, id methodArg) { 
    [_self doSomethingWith:methodArg]; 
}; 

y luego debe generar el IMP bloquear de forma dinámica, en esta ocasión, que pasa, "sí", la SEL, y cualquier argumento ...

void(*impFunct)(id, SEL, id) = (void*) imp_implementationWithBlock(impBlock); 

y añadirlo a su clase, además de una firma método exacto para todo el lechón (en este caso "[email protected]:@" , volverá vacía, objeto persona que llama, el argumento objeto)

class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "[email protected]:@"); 

se puede ver algunos buenos ejemplos de este tipo de runtime shenanigans, in one of my repos, here.

3

sé que esto ha sido contestada de hace mucho tiempo, pero todavía quiero compartir. Esto se puede hacer usando sel_registerName también.

El código de ejemplo en la pregunta puede reescribirse así:

+0

realidad, '' NSSelectorFromString'' mencionado por @ torsten-Marek utiliza '' sel_registerName'' bajo el capó. [Appledev] (https://developer.apple.com/documentation/foundation/1395294-nsselectorfromstring?language=objc): _ "NSSelectorFromString pasa una representación de caracteres UTF-8 codificada de aSelectorName a sel_registerName y devuelve el valor devuelto por esta función "_ – PLG

Cuestiones relacionadas