2008-12-01 52 views

Trả lời

71

Đây là một giải pháp dựa trên các chức năng thời gian chạy C:

class_copyMethodList trả về một danh sách các phương pháp lớp học cho một đối tượng Class có thể đạt được từ một vật.

#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

Câu trả lời này cung cấp cho bạn các phương thức lớp học. Nếu bạn muốn các phương thức mà đối tượng phản hồi để thay thế dòng này 'Method * mlist = class_copyMethodList (object_getClass (t), &mc);' với phương thức này 'Method * mlist = class_copyMethodList (t, &mc);' – bugloaf

+1

@bugloaf bình luận của bạn có ý nghĩa như thế nào chữ ký của object_getClass mong đợi một biến lớp? – abbood

+0

@abbood Bạn không hiểu gì về bình luận của tôi? Tôi chỉ cần kiểm tra lại tài liệu ngay bây giờ, và tôi đứng bởi bình luận của tôi 'object_getClass' mong đợi một đối tượng, và trả về lớp đối tượng, trong đó đối số là một cá thể.Nếu 'class_copyMethodList' được truyền vào một đối tượng lớp, nó sẽ trả về các phương thức lớp, nếu nó được truyền vào một đối tượng thông thường, nó sẽ trả về các phương thức trên đối tượng đó – bugloaf

1

Điều gì đó như thế này sẽ hoạt động (chỉ cần đặt nó vào đối tượng bạn tò mò). Ví dụ nếu bạn có một đối tượng đó là một đại biểu và muốn biết những gì 'móc' có sẵn này sẽ in ra thông điệp để cung cấp cho bạn đầu mối rằng:

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

Lưu ý rằng tôi đã khám phá này trong iPhone Developer của Cookbook vì vậy tôi không thể nhận tín dụng! Ví dụ đầu ra tôi nhận được từ một UIViewController mà thực hiện các giao thức <UITableViewDelegate, UITableViewDataSource>:

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 này không jive. Các đối số được cho là đến từ đâu? – nmr

+2

Điều này sẽ chỉ liệt kê các bộ chọn được truy vấn động tại thời gian chạy (như với Objective-C "các giao thức không chính thức"), không phải tất cả các bộ chọn mà đối tượng phản hồi. – rvalue

25

Tôi nghĩ thông thường bạn sẽ muốn làm điều đó trong giao diện điều khiển, thay vì làm lộn xộn mã của bạn với mã gỡ lỗi. Đây là cách bạn có thể làm điều đó trong khi gỡ lỗi trong LLĐB:

(Giả sử một đối tượng t)

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

Đây cũng là có thể với 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]))])) 
} 

Output:

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> 

Được thử nghiệm với trình mô phỏng 6 chạy iOS 9.2, Phiên bản Xcode 7.2 (7C68).

0

Lấy cảm hứng từ câu trả lời JAL 's, trong Swift bạn có thể làm:

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]) }) 
    } 
} 
Các vấn đề liên quan