2012-12-26 3 views
6

Ich habe mein Protokoll definiert. Ich habe zwei meiner Protokollmethoden als optional erwähnt. Wie kann ich während der Laufzeit herausfinden, ob die bestimmte Methode optional ist oder nicht? Gibt es eine Möglichkeit, das herauszufinden?Wie erkennt man eine Protokollmethode während der Laufzeit?

+2

Warum diese Informationen würden zur Laufzeit benötigt werden? (Nur neugierig.) –

+1

@NikolaiRuhe Ja, +1 für diesen Kommentar. Im Allgemeinen sollten wir keine Annahmen machen, sondern Testfunktionen. I. e., Sollte man anstelle von der Annahme, dass eine erforderliche Methode implementiert ist, nach "answerToSelector:" testen. –

+0

Oder Sie können ein Wörterbuch selbst mit dem Namen der Methoden als Schlüssel und seinem Wert als JA/NEIN erstellen, um zu überprüfen, ob es erforderlich ist oder nicht. –

Antwort

12

Dies sollte tun, was Sie wollen:

BOOL MethodInProtocolIsRequired(Protocol *protocol, SEL methodSelector) 
{ 
    struct objc_method_description methodDesc = protocol_getMethodDescription(protocol, methodSelector, YES, YES); 
    return methodDesc.name != NULL; 
} 

Bitte beachte, dass ich nicht auf die Ratsamkeit kommentieren dies mit in der Postleitzahl, besonders, weil Sie nicht erklärt haben, warum Sie dies tun möchten. Beachten Sie außerdem, dass diese Funktion NO zurückgibt, wenn ein Selektor für eine Methode angegeben wird, die das Protokoll nicht enthält. Das ist im Grunde vernünftig (schließlich, wenn ein Protokoll keine Methode enthält, ist es nicht erforderlich!), Aber Sie könnten die Funktion verfeinern, indem Sie prüfen, ob das Protokoll die Methode als optionale Methode enthält und etwas anderes zurückgibt alle drei Szenarien (erforderlich, optional, nicht im Protokoll).

EDIT: Einfaches Testprogramm hier: https://gist.github.com/4381753

+0

Ich sollte das wirklich tun anstatt meiner überkomplizierten Vorgehensweise. +1. (Kann ich das in meine Antwort aufnehmen?) –

+0

Natürlich, und ich sehe, du hast es schon getan :). –

+0

Yep, und ich stellte sicher, Attribution hinzufügen :) Diesmal bin ich es, der RTFM haben sollte ... -.- –

3

(ich weiß nicht, die Antwort aus der Spitze von meinem Kopf. 1 Minute googeln half mir.)

Sie können dies tun, um die protocol_copyMethodDescriptionList()-Funktion, den Teil der Objective-C-Laufzeit ist Bibliothek (libobjc). Das zweite Argument dieser Funktion ist ein boolesches Flag, das angibt, ob die im Protokoll zu kopierenden Methoden erforderlich sind. Wenn also eine Methode in der Liste enthalten ist, die von dieser Funktion zurückgegeben wird (die mit den entsprechenden Argumenten aufgerufen wird), ist sie eine erforderliche Methode.

SEL sctr = @selector(isThisMethod:requiredIn:theProtocol:); 

struct objc_method_description *methods; 
unsigned int nMethods; 
methods = protocol_copyMethodDescriptionList(
    objc_getProtocol("MyProtocolName"), // or @protocol(MyProtocolName) if you don't need this kind of dynamism 
    YES, // required? 
    YES, // instance method? (in general, protocols declare instance methods) 
    &nMethods 
); 

BOOL isRequired = NO; 
int i; 
SEL s; 
const char *sctrStr = sel_getName(sctr); 
for (i = 0; i < nMethods; i++) { 
    s = methods[i].name; 
    const char *sStr = sel_getName(s); 
    if (strcmp(sctrScr, sStr) == 0) { 
     isRequired = YES; 
     break; 
    } 
} 

free(methods); 

if (isRequired) { 
    // required 
} else { 
    // optional 
} 

Also, das ist möglich, aber es ist ein bisschen zuviel des Guten, und wie ich schon in meinem Kommentar zu Ihrer Frage erwähnt, sollten Sie nicht testen für ein Verfahren optional oder erforderlich ist, sollten Sie sich für einen Test Instanz reagiert auf einen bestimmten Selektor.

Edit: ja, anstatt das ganze Universum zu kopieren, hätte ich weiter in der Dokumentation gelesen. Wie Andrew Madsen darauf hingewiesen, kann dies auf ein paar Zeilen reduziert werden:

struct objc_method_description method; 
method = protocol_getMethodDescription(
    objc_getProtocol("MyProtocolName"), // or @protocol(MyProtocolName) 
    @selector(isThisSelector:required:) 
    YES, // required? 
    YES // instance method? 
); 

if (method.name != NULL) { 
    // required 
} else { 
    // optional 
} 
+1

Warum auf der Erde würde jemand seinen Upvote zu einem Downvote ändern? –

+1

Wenn Sie nur GNU c booleans verwenden würden, könnten Sie schließlich sagen, dass Sie eine Objective-C-Frage ohne ObjC beantwortet haben! (Extrem technisch aber). – CodaFi

+1

@CodaFi: Oder C99 'bool' /' _Bool'. –

Verwandte Themen