我有一个对象,我想列出它响应的所有选择器。感觉这应该是完全可能的,但我在找到 API 时遇到了麻烦。
Airsource Ltd
问问题
16810 次
7 回答
77
这是一个基于运行时 C 函数的解决方案:
给定可从对象获得的 Class 对象,class_copyMethodList 返回类方法列表。
#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 */
于 2008-12-01T05:54:52.647 回答
29
我认为通常您会希望在控制台中执行此操作,而不是让您的代码与调试代码混淆。在 lldb 中调试时,您可以这样做:
(假设一个对象 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]))); }
于 2013-11-06T08:43:37.673 回答
8
这在 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>
使用运行 iOS 9.2、Xcode 版本 7.2 (7C68) 的 6s 模拟器进行测试。
于 2016-02-10T02:09:32.960 回答
3
从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]) })
}
}
于 2017-05-15T23:06:22.297 回答
1
ARC实现
SomeClass *someClass = [[SomeClass alloc] init];
//List of all methods
unsigned int amountMethod = 0;
Method *methods = class_copyMethodList(someClass, &amountMethod);
for (unsigned int i = 0; i < amountMethod; i++) {
Method method = methods[i];
printf("\t method named:'%s' \n", sel_getName(method_getName(method)));
}
free(methods);
于 2019-03-28T20:07:45.877 回答
0
像这样的东西应该可以工作(只需将它放在您感兴趣的对象中)。例如,如果您有一个委托对象并且想知道有哪些“钩子”可用,这将打印出消息为您提供该线索:
-(BOOL) respondsToSelector:(SEL)aSelector {
printf("Selector: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:aSelector];
}
请注意,我在iPhone Developer's Cookbook中发现了这一点,所以我不能相信!例如,我从UIViewController
实现协议的 a 获得的输出<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.
于 2008-12-01T05:11:04.607 回答
0
如果你还想获得超类的选择器,你可以像这样循环:
Class c = [myObject class];
while (c != nil) {
int i = 0;
unsigned int mc = 0;
Method* mlist = class_copyMethodList(c, &mc);
NSLog(@"%d methods for %@", mc, c);
for(i = 0; i < mc; i++) {
const char* selName = sel_getName(method_getName(mlist[i]));
NSLog(@"Method #%d: %s", i, selName);
}
free(mlist);
c = [c superclass];
}
于 2022-01-04T02:13:34.717 回答