2009-08-25 11 views
6

¿Cómo puse un "gancho" en un objeto para poder ver qué mensajes se están enviando a él? (es decir, hacer un NSLog() cada vez que se envía un mensaje a un objeto).Capturar todos los métodos/llamadas de mensajes en un objeto

Creo recordar recordar haberlo hecho antes, pero se me olvida cómo. Estoy pensando que podría ayudarme a rastrear por qué parte de mi código no funciona.

Respuesta

18

También puede usar objective-c forwarding. Básicamente, puede crear un objeto proxy que registre los métodos y luego reenvíe la llamada al original. Vea mi blog post para más detalles.

@interface LoggerProxy : NSObject 
{ 
    id original; 
} 

- (id)initWithOriginal:(id) value; 

@end 
@implementation LoggerProxy 

- (id) initWithOriginal:(id)value 
{ 
    if (self = [super init]) { 
     original = value; 
    } 
    return self; 
} 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel 
{ 
    NSMethodSignature *sig = [super methodSignatureForSelector:sel]; 
    if(!sig) 
    { 
     sig = [original methodSignatureForSelector:sel]; 
    } 
    return sig; 
} 

- (void)forwardInvocation:(NSInvocation *)inv 
{ 
    NSLog(@"[%@ %@] %@ %@", original, inv,[inv methodSignature], 
     NSStringFromSelector([inv selector])); 
    [inv invokeWithTarget:original]; 
} 

@end 
+2

Acabo de probar esto y funciona hasta cierto punto. Lo estoy probando con MKPinAnnotationView y se bloquea con una excepción NSInvalidArgumentException cuando intenta llamar al [supermodelo MKPinAnnotationView]. Entonces, ¿intentó enviarlo a un objeto que no tiene este método? –

+0

El enlace de su blog no está actualizado. – mahboudz

0

Puede utilizar un objeto NSProxy y anular el método forwardInvocation:.

8

La mejor manera de hacerlo es con dtrace o un script de instrumentos. Uso de DTrace puede hacer lo siguiente:

escribir la siguiente secuencia de comandos como objc-calls.d

#pragma D option quiet 
objc$target:::entry 
{ 
    printf("%s %s\n", probemod, probefunc); 
} 

A continuación, ejecute la aplicación usando la secuencia de comandos:

setenv DYLD_SHARED_REGION avoid 
sudo dtrace -s objc-calls.d -c /Path/To/Your/App/Binary 

También es posible construir una costumbre Instrumento usando una sonda dtrace similar.

+0

He marcado su ayuda como marcador, es útil, pero la otra proporciona una solución más rápida/más fácil. Gracias. – Jacob

1

Si seguís el comentario de Louis Gerbarg del año pasado, también es útil poder filtrar fácilmente por nombre de clase.

Prueba el siguiente script D:

#!/usr/sbin/dtrace -s 
#pragma D option quiet 
objc$target:::entry 
/strstr(probemod,$$1) != NULL/ 
{ 
    printf("%s %s\n", probemod, probefunc); 
} 

guardarlo, chmod a+x objc-calls.d, y luego hacer sudo objc-calls.d -c /Your/Binary NSObject para ver sólo las invocaciones relacionadas con NSObject (y sus categorías).

Cuestiones relacionadas