代码之家  ›  专栏  ›  技术社区  ›  Airsource Ltd

列出Objective-C对象的选择器

  •  35
  • Airsource Ltd  · 技术社区  · 17 年前

    我有一个对象,我想列出它响应的所有选择器。感觉这应该是完全可能的,但是我很难找到API。

    5 回复  |  直到 9 年前
        1
  •  71
  •   diciu    17 年前

    这是基于运行时C函数的解决方案:

    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 */
    
        2
  •  25
  •   José Manuel Sánchez    12 年前

    我认为通常您希望在控制台中这样做,而不是将代码与调试代码混在一起。这是在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]))); }
    
        3
  •  5
  •   JAL    10 年前

    这也可以通过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模拟器进行测试。

        4
  •  1
  •   Jason Plank Maksim Kondratyuk    14 年前

    像这样的东西应该管用(把它放在你好奇的物体里就行了)。例如,如果您有一个作为委托的对象,并且想要知道哪些“挂钩”可用,那么这将打印出消息来给您提供线索:

    -(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.
    
        5
  •  1
  •   Community Mohan Dere    9 年前

    灵感来自 JAL 答案是,你可以迅速做到:

    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]) })
        }
    }
    
    推荐文章