Je sais comment créer un SEL
au moment de la compilation en utilisant @selector(MyMethodName:)
mais ce que je veux faire est de créer dynamiquement un sélecteur à partir d'un NSString
. Est-ce seulement possible?
Qu'est-ce que je peux faire:
SEL selector = @selector(doWork:);
[myobj respondsToSelector:selector];
Ce que je veux faire: (pseudo-code, cela ne fonctionne évidemment pas)
SEL selector = selectorFromString(@"doWork");
[myobj respondsToSelector:selector];
J'ai recherché la documentation de l'API Apple Apple, mais je n'ai pas trouvé de moyen qui ne repose pas sur la syntaxe @selector(myTarget:)
au moment de la compilation.
Je ne suis pas un programmeur Objective-C, simplement un sympathisant, mais peut-être NSSelectorFromString est ce dont vous avez besoin. Il est mentionné explicitement dans le Runtime Reference que vous pouvez l'utiliser pour convertir une chaîne en sélecteur.
Selon la documentation XCode, votre pseudo-code est fondamentalement correct.
Il est plus efficace d'affecter des valeurs aux variables SEL au moment de la compilation avec la directive @selector (). Cependant, dans certains cas, un programme peut avoir besoin de convertir une chaîne de caractères en sélecteur au moment de l'exécution. Cela peut être fait avec la fonction NSSelectorFromString:
setWidthHeight = NSSelectorFromString(aBuffer);
Edit: Bummer, trop lent. : P
Je dois dire que c'est un peu plus compliqué que les réponses des répondants précédents ne le suggèrent ... si vous voulez vraiment créer un sélecteur ... pas seulement "en appeler un" que vous avez "autour de vous" ...
Vous devez créer un pointeur de fonction qui sera appelé par votre "nouvelle" méthode .. donc pour une méthode comme [self theMethod:(id)methodArg];
, vous écririez ...
void (^impBlock)(id,id) = ^(id _self, id methodArg) {
[_self doSomethingWith:methodArg];
};
et ensuite vous devez générer dynamiquement le bloc IMP
, cette fois en passant "self", le SEL
et tous les arguments ...
void(*impFunct)(id, SEL, id) = (void*) imp_implementationWithBlock(impBlock);
et ajoutez-le à votre classe, ainsi qu'une signature de méthode précise pour l'ensemble du meunier (dans ce cas "v@:@"
, retour nul, appelant objet, argument objet)
class_addMethod(self.class, @selector(theMethod:), (IMP)impFunct, "v@:@");
Vous pouvez voir quelques bons exemples de ce genre de shenanigans d'exécution, dans l'un de mes repos, ici.
Je sais que cela a été répondu depuis longtemps, mais je veux quand même partager. Cela peut être fait en utilisant sel_registerName
aussi.
L'exemple de code dans la question peut être réécrit comme ceci:
SEL selector = sel_registerName("doWork:");
[myobj respondsToSelector:selector];