Список селекторов для объекта Objective-C - PullRequest
35 голосов
/ 01 декабря 2008

У меня есть объект, и я хочу перечислить все селекторы, на которые он отвечает. Такое ощущение, что это вполне возможно, но у меня проблемы с поиском API.

Ответы [ 6 ]

72 голосов
/ 01 декабря 2008

Это решение, основанное на функциях среды выполнения C:

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 */
25 голосов
/ 06 ноября 2013

Я думаю, что обычно вы хотите сделать это в консоли, вместо того, чтобы загромождать свой код отладочным кодом. Вот как вы можете сделать это при отладке в 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]))); }
6 голосов
/ 10 февраля 2016

Это также возможно с 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>

Протестировано на симуляторе 6s под управлением iOS 9.2, Xcode Version 7.2 (7C68).

1 голос
/ 16 мая 2017

Вдохновившись ответом 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]) })
    }
}
1 голос
/ 01 декабря 2008

Нечто подобное должно работать (просто поместите это в объект, который вас интересует). Например, если у вас есть объект, который является делегатом, и вы хотите знать, какие «крючки» доступны, это выведет на экран сообщения, которые дадут вам эту подсказку:

-(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.
0 голосов
/ 28 марта 2019

реализация 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);
...