Klassenmethodenäquivalent von -respondsToSelector:

68

Gibt es eine Klassenmethode, die äquivalent zu ist -respondsToSelector:?

So etwas wie +respondsToSelector:?

Der Grund, den ich -respondsToSelector:frage, ist, dass ich bei der Implementierung auf Klassenebene eine Compiler-Warnung erhalte: "found '-respondsToSelector:' anstelle von '+ respondsToSelector:' in Protokollen".

Der Code sieht folgendermaßen aus:

Class <SomeProtocol> someClass = [someInstance class];

if ([someClass respondsToSelector:@selector(someSelector:)]) {
    someVar = [someClass someSelector:someData];
}
erster Beantworter
quelle

Antworten:

83

Update nach dem Bearbeiten:

respondsToSelector:Wie Sie wahrscheinlich wissen, reagiert ein Klassenobjekt einwandfrei . In einer Testanwendung kann ich beide der folgenden Aktionen ohne Compiler-Warnungen ausführen:

NSLog(@"Responds to selector? %i", [MyObject respondsToSelector:@selector(respondsToSelector:)]);
NSLog(@"Responds to selector? %i", [[MyObject class] respondsToSelector:@selector(respondsToSelector:)]);

Sie haben jedoch ein Protokoll für Ihre Variable deklariert, sodass davon ausgegangen wird, dass das Klassenobjekt, auf das Sie zeigen, diese Methoden implementiert. Die einfachste Lösung wäre, someClassals idzum Zweck des Anrufs zu besetzen respondsToSelector:. Eine etwas sauberere Lösung wäre, Ihre eigene zu @protocoldeklarieren +respondsToSelector:(SEL)selector, die deklariert , und dann someClasswie folgt zu deklarieren :

Class<SomeProtocol, ClassRespondingToSelector> someClass = ...

Stellen Sie schließlich sicher, dass Sie einen Fehler bei Apple unter http://bugreporter.apple.com melden . Fügen Sie eine einfache Testanwendung hinzu, damit klar ist, was Sie tun. Sie begrüßen solche Fehlerberichte, auch wenn sie in der Vergangenheit eingereicht wurden, da dies ihnen hilft, die Korrekturen zu priorisieren.

Schlussbemerkung: Dies geschieht wahrscheinlich, weil Sie theoretisch ein von NSObject völlig getrenntes Stammobjekt implementieren könnten und in diesem Fall nicht darauf reagieren würden-respondsToSelector: . -[NSObject respondsToSelector:]wird tatsächlich im NSObjectProtokoll deklariert , nicht in der Klassendefinition. Das NSObjectProtokoll ist tatsächlich der Ort, an dem das meiste, was Sie als NSObjecttatsächlich kennen, lebt. Man könnte argumentieren, dass +respondsToSelector:das auch drin sein sollte, aber ab sofort ist es nicht mehr so. Und da Sie eine Protokollliste bereitgestellt haben und die Methode nicht vorhanden ist, erhalten Sie eine Warnung, um sicherzustellen, dass Sie wissen, was Sie tun.

BJ Homer
quelle
Ich glaube in diesem Fall würde er tatsächlich in die Klasse werfen wollen, nicht in die ID.
Joseph Lennox
7
Dies ist entweder entfernte Funktionalität oder die Antwort ist unklar. Classreagiert nicht auf respondsToSelector:.
RileyE
Versuch es. Es ist nicht in der Kopfzeile, aber tunid classObject = [SomeClass class]; [classObject respondsToSelector:]
BJ Homer
1
Es funktioniert tatsächlich, wie BJ Homer sagte, es ist nicht im Header und daher keine automatische Vervollständigung durch Xcode. Das hat mich zweifeln lassen. Sie müssen es vollständig eingeben.
Wolfrevo
@ RileyE stimmte zu, ich stand auch vor diesem Problem, kann das Äquivalent respondToSelectorin der nicht finden Class.
Ratul Sharker
9

Nun, eine Klassenmethode ist nur eine Methode des Klassenobjekts, daher sollten Sie dies einfach tun können

[MyClass respondsToSelector:@selector(...)]
newacct
quelle
Ich erhalte eine Compiler-Warnung: "gefunden '-respondsToSelector:' anstelle von '+ respondsToSelector:' in Protokoll (en)". Wie entferne ich diese Compiler-Warnung?
Ersthelfer
Ich kann die Compiler-Warnung entfernen, indem ich das Protokolltyp-Qualifikationsmerkmal '<SomeProtocol>' lösche. Warum ist das so? Ist diese Syntax nicht korrekt?
Ersthelfer
3
Erstantwort: Objective-C ist eine dynamische Sprache. Wenn Sie eine Nachricht an einen Classoder idohne weitere Qualifizierung dieses Typs (mit einem Protokoll) senden , geht der Compiler davon aus, dass Sie selbst eine Art Antwort auf Selektor oder eine Art Klassenprüfung durchführen. Wenn Sie jedoch ein Protokoll oder (zum Beispiel) eine bestimmte Klasse angeben, wird es hilfreich und führt die Prüfung für Sie durch. Da das Protokoll, mit dem Sie die Variable deklariert haben, keine +respondsToSelector:Deklaration enthält, gibt der Compiler eine Warnung aus.
Peter Hosey
Ich habe festgestellt, dass das Casting mit Protokollverhalten in Xcode 9 anders ist. Es akzeptiert das Casting dort, jedoch nicht in 8 und niedriger.
Will Larche
5

instancesRespondToSelector:Seit iOS 2.0 können Sie Folgendes verwenden: Wo können Sie also mit einer Instanz einer Klasse arbeiten ?

[myInstance respondsToSelector: @selector(...)];

Mit einer Klasse können Sie verwenden

[myClass instanceRespondsToSelector: @selector(...)];
// or
[[myInstance class] instanceRespondsToSelector: @selector(...)];

Welches wird sich so verhalten +(BOOL) respondsToSelector

Hugo Scott-Slade
quelle
6
Dies würde antworten, wenn Instanzen der Klasse auf den Selektor antworten würden, nicht wenn die Klasse selbst statisch auf den Selektor antworten würde.
Jonny
2

Ich denke, Sie haben gefragt: Können Sie eine Klasse fragen, ob sie darauf reagiert +someMethododer nicht? Mit anderen Worten, wenn Sie an die Cocoa Touch-APIs denken, möchten Sie:

[ [ UIView class ] respondsToSelector: @selector( buttonWithType: ) ] -> NO
[ [ UIButton class ] respondsToSelector: @selector( buttonWithType: ) ] -> YES

Aber was ich oben geschrieben habe, funktioniert nicht wie gewünscht. respondsToSelector:geht es nur um Instanzmethoden. (Somit geben beide Aufrufe NO zurück.) Innerhalb der Cocoa-APIs gibt es kein Äquivalent respondsToSelector:für eine Klasse.

Sie können jedoch anrufen class_getClassMethod. Wenn das Ergebnis nicht-NULL ist, die Klassenmethode Sie fragen ist vorhanden und man kann es nennen.

Escouten
quelle
8
Das ist falsch. respondsToSelector:funktioniert gut mit ClassObjekten, um die Existenz von Klassenmethoden zu melden.
Dave DeLong
Ich stimme diesem Typen zu, weil er mit seinem class_getClassMethodAnsatz tatsächlich richtig lag . Wenn ich genug Geduld gehabt hätte, um den gesamten Thread zu lesen, müsste ich nicht dieselbe Lösung neu erfinden.
Bioffe
1
Ich-stimmen diese, weil Klassenmethoden sind Instanzmethoden auf das Klassenobjekt.
user102008
4
-1 Sie beschreiben das Verhalten von +instancesRespondToSelector:. -respondsToSelector:auf einem Klassenobjekt funktioniert ganz anders.
0

In Ziel C sind Klassen auch Objekte, sodass Sie die Objektnachrichten senden können. Insbesondere können Sie -respondsToSelector:von einer Klasse verlangen . Sie können jedoch keine Methoden auf Klassenebene an Objekte senden, die keine Klassen sind.

SK9
quelle