ultima tutorial programación objective mundo logo lenguaje hola caracteristicas objective-c methods runtime introspection

tutorial - objective-c++



¿Es posible usar las características de tiempo de ejecución de Objective-C para determinar de dónde se llamó un método? (4)

No con el tiempo de ejecución. Todos los mensajes enviados finalmente funcionan en una llamada de función a lo largo de las líneas de objc_msgSend(id receiver, SEL selector, /*method arguments*/...) . Como puede ver, no se pasa información sobre el objeto que envía el mensaje. Probablemente sea posible determinar el objeto que llama caminando sobre la pila, pero de esa manera se encuentra la locura. La única manera práctica de saber quién llamó al método es darle un argumento de sender como todos los métodos de IBAction.

Objective-C usa un sofisticado sistema de transmisión de mensajes cuando un objeto llama a un método en otro objeto. Quiero saber si es posible, dentro del método llamado, determinar cuál fue el objeto llamante.

Por ejemplo:

@implementation callingClass - (void)performTest { calledObject = [[[calledClass alloc] init] autorelease]; id result = [calledObject calledMethod]; assert(result == this); } @end @implementation calledClass - (id)calledMethod { id objectThatCalledThisMethod = ... // <-- what goes here? return objectThatCalledThisMethod; } @end

¿Qué podría escribir en la línea comentada para hacer que la aserción pase cuando ejecuto performTest ?


No, no puedes determinar qué objeto te llamó. Bueno, técnicamente, podría ser posible hurgar en la pila, pero ciertamente no es práctico para el código real.

Si observa la mayoría de los métodos de delegado, puede ver que los formatos de llamada de delegado estándar se ven así:

- (NSSize) windowWillResize:(NSWindow *)window toSize:(NSSize)proposedFrameSize; - (BOOL) windowShouldClose:(id)window; - (void) windowWillMove:(NSNotification *)notification;

Observe cómo se pasa la ventana (llamador) como primer argumento y cómo "ventana" es la primera parte del nombre del método. En el último caso, el llamador de ventana está implícito en NSNotification (notification.object es la ventana).


Podría tratar de obtener su propia clase de NSInvocation que transmita la información de la persona que llama. O envuelva una clase alrededor de NSInvocation para volver a implementar algunas de las llamadas allí.


Espero que esto ayude:

NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1]; // Example: 1 UIKit 0x00540c89 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163 NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:@" -[]+?.,"]; NSMutableArray *array = [NSMutableArray arrayWithArray:[origen componentsSeparatedByCharactersInSet:separatorSet]]; [array removeObject:@""]; NSLog(@"Pila = %@", [array objectAtIndex:0]); NSLog(@"Framework = %@", [array objectAtIndex:1]); NSLog(@"Memory address = %@", [array objectAtIndex:2]); NSLog(@"Class caller = %@", [array objectAtIndex:3]); NSLog(@"Function caller = %@", [array objectAtIndex:4]); NSLog(@"Line caller = %@", [array objectAtIndex:5]);