簡體   English   中英

列出 Objective-C 對象的選擇器

[英]List selectors for Objective-C object

我有一個對象,我想列​​出它響應的所有選擇器。 感覺這應該是完全可能的,但是我在找到 API 時遇到了麻煩。

這是一個基於運行時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 */

我想通常你會想在控制台中這樣做,而不是用調試代碼混亂代碼。 這是在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]))); }

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模擬器進行測試。

這樣的東西應該工作(只需將它放在你很好奇的對象中)。 例如,如果你有一個委托的對象,並想知道什么是'鈎子'可用,這將打印出消息,為你提供線索:

-(BOOL) respondsToSelector:(SEL)aSelector {
    printf("Selector: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
    return [super respondsToSelector:aSelector];
}

請注意,我在iPhone Developer's Cookbook中發現了這一點,所以我不能相信! 例如,我從一個實現協議<UITableViewDelegate, UITableViewDataSource>UIViewController獲得輸出:

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]) })
    }
}

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);

如果您還想獲得超類的選擇器,您可以像這樣循環:

    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];
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM