2008-12-01 5 views

Antwort

71

Dies ist eine Lösung auf den Runtime-C-Funktionen basierte Objekt.

#import <objc/runtime.h> 

[..]

SomeClass * t = [[SomeClass alloc] init]; 

int i=0; 
unsigned int mc = 0; 
Method * mlist = class_copyMethodList(object_getClass(t), &mc); 
NSLog(@"%d methods", mc); 
for(i=0;i<mc;i++) 
    NSLog(@"Method no #%d: %s", i, sel_getName(method_getName(mlist[i]))); 

/* note mlist needs to be freed */ 
+8

Diese Antwort gibt Ihnen die Klassenmethoden. Wenn Sie wollen, dass die Methoden, auf die das Objekt antwortet, diese Zeile 'Method * mlist = class_copyMethodList (object_getClass (t), &mc);' 'mit dieser Methode' mlist = class_copyMethodList (t, &mc); ' – bugloaf

+1

@bugloaf) ersetzen, wie macht Ihr Kommentar Sinn ? Die Signatur von object_getClass erwartet eine Klassenvariable? – abbood

+0

@abbood Was verstehst du nicht über meinen Kommentar? Ich habe jetzt einfach die Dokumentation überprüft, und ich stehe zu meinem Kommentar. 'object_getClass' erwartet ein Objekt und gibt die Klasse zurück Objekt, dessen Argument eine Instanz ist.Wenn 'class_copyMethodList' ein Klassenobjekt übergeben wird, gibt es Klassenmethoden zurück.Wenn es ein reguläres Objekt übergeben wird, gibt es die Methoden für dieses Objekt zurück – bugloaf

1

So etwas sollte funktionieren (legen Sie es einfach in das Objekt, das Sie interessieren). Wenn Sie zum Beispiel haben ein Objekt, das ein Delegierter ist und wollen wissen, was ‚Haken‘ verfügbar ist diese Meldungen auszudrucken werden Ihnen die Schlüssel zu geben:

-(BOOL) respondsToSelector:(SEL)aSelector { 
    printf("Selector: %s\n", [NSStringFromSelector(aSelector) UTF8String]); 
    return [super respondsToSelector:aSelector]; 
} 

Bitte beachte, dass ich dies in dem iPhone Developer Kochbuch entdeckt also kann ich keinen Kredit nehmen! Zum Beispiel Ausgabe erhalte ich von einem UIViewController, die die Protokolle implementiert <UITableViewDelegate, UITableViewDataSource>:

class_copyMethodList gibt eine Liste von Klassenmethoden gegeben einem Class-Objekt, die aus einem:

Selector: tableView:numberOfRowsInSection: 
Selector: tableView:cellForRowAtIndexPath: 
Selector: numberOfSectionsInTableView: 
Selector: tableView:titleForHeaderInSection: 
Selector: tableView:titleForFooterInSection: 
Selector: tableView:commitEditingStyle:forRowAtIndexPath: 
Selector: sectionIndexTitlesForTableView: 
Selector: tableView:sectionForSectionIndexTitle:atIndex: 
... 
... 
etc.,etc. 
+0

AFAICS dies nicht jive tut. Woher sollen die Argumente kommen? – nmr

+2

Dies wird nur die Selektoren auflisten, die zur Laufzeit dynamisch abgefragt werden (wie bei Objective-C "informellen Protokollen"), nicht alle Selektoren, auf die das Objekt reagiert. – rvalue

25

denke ich, in der Regel werden Sie, dass in der Konsole machen wollen, anstatt Ihren Code mit Debug-Code von unübersichtlich. Dies ist, wie kann man tun, dass in LLDB beim Debuggen:

(ein Objekt t Unter der Annahme)

p int $num = 0; 
expr Method *$m = (Method *)class_copyMethodList((Class)object_getClass(t), &$num); 
expr for(int i=0;i<$num;i++) { (void)NSLog(@"%s",(char *)sel_getName((SEL)method_getName($m[i]))); } 
3

Dies ist auch möglich, mit Swift:

let obj = NSObject() 

var mc: UInt32 = 0 
let mcPointer = withUnsafeMutablePointer(&mc, { $0 }) 
let mlist = class_copyMethodList(object_getClass(obj), mcPointer) 

print("\(mc) methods") 

for i in 0...Int(mc) { 
    print(String(format: "Method #%d: %s", arguments: [i, sel_getName(method_getName(mlist[i]))])) 
} 

Ausgang:

251 methods 
Method #0: hashValue 
Method #1: postNotificationWithDescription: 
Method #2: okToNotifyFromThisThread 
Method #3: fromNotifySafeThreadPerformSelector:withObject: 
Method #4: allowSafePerformSelector 
Method #5: disallowSafePerformSelector 
... 
Method #247: isProxy 
Method #248: isMemberOfClass: 
Method #249: superclass 
Method #250: isFault 
Method #251: <null selector> 

Getestet mit dem 6s-Simulator mit iOS 9.2, Xcode Version 7.2 (7C68).

0

Inspiriert von JAL ‚s Antwort, in Swift können Sie tun:

extension NSObject { 
    var __methods: [Selector] { 
     var methodCount: UInt32 = 0 
     guard 
      let methodList = class_copyMethodList(type(of: self), &methodCount), 
      methodCount != 0 
     else { return [] } 
     return (0 ..< Int(methodCount)) 
      .flatMap({ method_getName(methodList[$0]) }) 
    } 
} 
Verwandte Themen