2008-09-22 4 views
89

Ich weiß, wie man eine SEL zur Kompilierzeit mit @selector(MyMethodName:) erstellen, aber was ich tun möchte, ist ein Selektor dynamisch von NSString zu erstellen. Ist das überhaupt möglich?Wie kann ich dynamisch einen Selektor zur Laufzeit mit Objective-C erstellen?

Was ich tun kann:

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

Was ich tun möchte: (Pseudo-Code, dies offensichtlich nicht funktioniert)

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

Ich habe die Apple-API-Dokumentation gesucht, aber haben keinen Weg gefunden, der nicht auf der Kompilierungszeit @selector(myTarget:) Syntax beruht.

Antwort

175

Ich bin kein Objective-C-Programmierer, nur ein Sympathisant, aber vielleicht NSSelectorFromString ist, was Sie brauchen. Es ist explizit in der Runtime Reference erwähnt, dass Sie es verwenden können, um eine Zeichenfolge in einen Selektor zu konvertieren.

+5

ich in meinem Google-fu auffrischen müssen. das ist genau das, was ich gesucht habe (oder nicht war). – craigb

+0

Nun, ich hatte immer noch die Links in meinen Lesezeichen, seit ich die Dokumente von Objective-C 2.0 vor ein paar Tagen gelesen habe. –

40

Gemäß der XCode-Dokumentation wird Ihr psuedocode grundsätzlich richtig.

Es ist am effizientesten, SEL-Variablen zur Kompilierzeit mit der @selector() -Direktive Werte zuzuweisen. In einigen Fällen muss ein Programm jedoch möglicherweise zur Laufzeit eine Zeichenfolge in einen Selektor konvertieren. Dies kann mit der NSSelectorFromString Funktion erfolgen:

setWidthHeight = NSSelectorFromString(aBuffer);

Edit: Bummer, zu langsam. : P

+2

'NSStringFromSelector (@" doWork ")' konvertiert es andersrum (nur fyi) – bendytree

+8

Ich denke, Sie meinen, NSStringFromSelector (@selector (doWork)) – jpswain

+0

Und was soll dieser Selektor angeblich tun? Sollten wir nicht einen Block oder etwas spezifizieren? –

8

Ich habe würde zu sagen, dass es ein wenig komplizierter ist als die Antworten der vorherigen Befragten könnte darauf hindeuten, ... wenn man in der Tat ... wirklich einen Wähler wollen schaffen nicht nur „nennen ein "dass man‚herumliegen‘...

Sie benötigen einen Funktionszeiger zu erstellen, die von Ihrem heißen wird‚.. neue‘Methode so für ein Verfahren wie [self theMethod:(id)methodArg];, würden Sie schreiben ...

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

und dann müssen Sie die IMP generieren dynamisch blockieren, diesmal vorbei, „Selbst“, das SEL, und alle Argumente ...

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

und es zu Ihrer Klasse hinzufügen, zusammen mit einer genauen Methodensignatur für den gesamten Sauger (in diesem Fall "[email protected]:@" , Leere Rückkehr, Objekt Anrufer, Objekt Argument)

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

Sie können einige gute Beispiele für diese Art von runtime shenanigans, in one of my repos, here.

3

sehen ich weiß, das für längst beantwortet wurde, aber noch will ich teilen. Dies kann auch mit sel_registerName erfolgen.

Das Codebeispiel in der Frage kann wie folgt neu geschrieben werden:

+0

Tatsächlich verwendet '' NSSelectorFromString'', das von @ torsten-marek erwähnt wird, '' sel_registerName'' unter der Haube. [appledev] (https://developer.apple.com/documentation/foundation/1395294-nsselectorfromstring?language=objc): _ "NSSelectorFromString übergibt eine UTF-8-codierte Zeichendarstellung von aSelectorName an sel_registerName und gibt den von dieser Funktion zurückgegebenen Wert zurück "_ – PLG

Verwandte Themen