objective-c selector

objective c - Lista de selectores para el objeto Objective-C



(5)

Algo así debería funcionar (simplemente colócalo en el objeto que te causa curiosidad). Por ejemplo, si tiene un objeto que es un delegado y desea saber qué ''ganchos'' están disponibles, esto imprimirá los mensajes para darle esa pista:

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

Tenga en cuenta que descubrí esto en el libro de cocina del desarrollador de iPhone, ¡ así que no me puedo atribuir el mérito! Por ejemplo, la salida que obtengo de un UIViewController que implementa los protocolos <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.

Tengo un objeto y quiero enumerar todos los selectores a los que responde. Parece que esto debería ser perfectamente posible, pero tengo problemas para encontrar las API.


Creo que normalmente querrá hacer eso en la consola, en lugar de saturar su código con código de depuración. Esta es la forma de hacerlo mientras se depura en lldb:

(Suponiendo un objeto 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]))); }


Esta es una solución basada en las funciones C de tiempo de ejecución:

class_copyMethodList devuelve una lista de métodos de clase dado un objeto Class que se puede obtener de un objeto.

#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 */


Esto también es posible con 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]))])) }

Salida:

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>

Probado con el simulador 6s con iOS 9.2, Xcode versión 7.2 (7C68).


Tomando la inspiración de la respuesta de JAL , en Swift puedes hacer:

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