¿Cómo puedo crear dinámicamente un selector en tiempo de ejecución con Objective-C?

StackOverflow https://stackoverflow.com/questions/112643

  •  02-07-2019
  •  | 
  •  

Pregunta

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 un NSString.¿Es esto siquiera posible?

Que puedo hacer:

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

Lo que quiero hacer:(pseudocó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 dependa del tiempo de compilación. @selector(myTarget:) sintaxis.

¿Fue útil?

Solución

No soy un programador de Objective-C, simplemente un simpatizante, pero tal vez NSSelectorFromString es lo que necesitas.Se menciona explícitamente en el Referencia de tiempo de ejecución que puedes usarlo para convertir una cadena en un selector.

Otros consejos

Según la documentación de XCode, su psuedocódigo 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, es posible que un programa necesite convertir una cadena de caracteres en un selector en tiempo de ejecución.Esto se puede hacer con la función NSSelectorFromString:

setWidthHeight = NSSelectorFromString(aBuffer);

Editar:Qué lástima, demasiado lento.:PAG

Tendría que decir eso es un poco más complicado de lo que las respuestas de los encuestados anteriores podrían sugerir...si realmente quieres crear un selector...no simplemente "llamar a uno" que "tienes por ahí"...

Debe crear un puntero de función que será llamado por su método "nuevo".entonces para un método como [self theMethod:(id)methodArg];, escribirías...

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

y luego necesitas generar el IMP bloquear dinámicamente, esta vez, pasando, "yo", el SEL, y cualquier argumento...

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

y agréguelo a su clase, junto con una firma de método precisa para todo el tonto (en este caso "v@:@", retorno nulo, llamador de objeto, argumento de objeto)

 class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "v@:@");

Puedes ver algunos buenos ejemplos de este tipo de travesuras en tiempo de ejecución, en uno de mis repositorios, aquí.

Sé que esto ya fue respondido hace mucho tiempo, pero aún así quiero compartirlo.Esto se puede hacer usando sel_registerName también.

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

SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top