Como posso dinamicamente criar um seletor em tempo de execução com Objective-C?
-
02-07-2019 - |
Pergunta
Eu sei como criar um SEL
em tempo de compilação usando @selector(MyMethodName:)
mas o que eu quero fazer é criar um seletor de forma dinâmica a partir de um NSString
. Isto é mesmo possível?
O que posso fazer:
SEL selector = @selector(doWork:);
[myobj respondsToSelector:selector];
O que eu quero fazer: (código pseudo, isso, obviamente, não funciona)
SEL selector = selectorFromString(@"doWork");
[myobj respondsToSelector:selector];
Eu tenho procurado a documentação da API da Apple, mas não encontrei uma maneira que não contam com a sintaxe em tempo de compilação @selector(myTarget:)
.
Solução
Eu não sou um programador Objective-C, apenas um simpatizante, mas talvez NSSelectorFromString é o que você precisa. É explicitamente mencionado na Runtime Referência que você pode usar -lo para converter uma string para um seletor.
Outras dicas
De acordo com a documentação XCode, o seu psuedocode basicamente acerta.
É mais eficiente para valores atribuir a variáveis ??SEL em tempo de compilação com a directiva @selector (). No entanto, em alguns casos, um programa pode precisar converter uma cadeia de caracteres de um seletor em tempo de execução. Isso pode ser feito com a função NSSelectorFromString:
setWidthHeight = NSSelectorFromString(aBuffer);
Edit: Bummer, muito lento. : P
Eu teria que dizer que é um pouco mais complicado do que respostas dos entrevistados anteriores pode sugerir ... se você de fato quer realmente criar um selector . .. não apenas "chamada de um" que "tem que volta" ...
Você precisa criar um ponteiro de função que será chamado pelo seu método "novo" .. assim para um método como [self theMethod:(id)methodArg];
, você escreveria ...
void (^impBlock)(id,id) = ^(id _self, id methodArg) {
[_self doSomethingWith:methodArg];
};
e então você precisa para gerar o bloco IMP
dinamicamente, desta vez, de passagem, "eu", o SEL
, e quaisquer argumentos ...
void(*impFunct)(id, SEL, id) = (void*) imp_implementationWithBlock(impBlock);
e adicioná-lo à sua classe, juntamente com uma assinatura preciso método para todo o otário (neste caso "v@:@"
, de retorno vazio, objeto chamador, o argumento de objeto)
class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "v@:@");
Você pode ver alguns bons exemplos deste tipo de runtime travessuras , em um dos meus repos, aqui.
Eu sei que este foi respondida por há muito tempo, mas ainda assim eu quero compartilhar. Isso pode ser feito usando sel_registerName
também.
O código de exemplo a questão pode ser reescrita assim:
SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];