Tôi có một đối tượng và tôi muốn liệt kê tất cả các bộ chọn mà nó phản hồi. Nó cảm thấy như thế này là hoàn toàn có thể, nhưng tôi đang gặp khó khăn khi tìm kiếm các API.Danh sách các bộ chọn cho đối tượng Objective-C
Trả lời
Đâ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 */
Đ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.
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]))); }
Đâ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).
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â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
@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
@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