列出Objective-C对象的select器
我有一个对象,我想列出它所响应的所有select器。 感觉这应该是完全可能的,但是我很难find这些API。
这是一个基于运行时C函数的解决scheme:
class_copyMethodList返回给定可从对象获取的Class对象的类方法列表。
#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 */
我想通常你会想在控制台中这样做,而不是用debugging代码混淆你的代码。 在lldb中debugging的时候,你可以这样做:
(假设一个对象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]))); }
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]))])) }
输出:
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>
testing运行iOS 9.2的Xs版本7.2(7C68)的6s模拟器。
像这样的东西应该工作(只要把它放在你好奇的对象)。 例如,如果你有一个对象是一个委托,并想知道有什么“钩子”可用,这将打印出消息给你的线索:
-(BOOL) respondsToSelector:(SEL)aSelector { printf("Selector: %s\n", [NSStringFromSelector(aSelector) UTF8String]); return [super respondsToSelector:aSelector]; }
请注意,我在iPhone开发人员手册中发现了这一点,所以我不能信任! 例如输出我从一个UIViewController
实现的协议<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.
从JAL的回答中得到灵感,在Swift中你可以这样做:
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]) }) } }