2009-08-25 9 views
6

Come si inserisce un "aggancio" su un oggetto in modo da poter vedere quali messaggi vengono inviati ad esso? (es. fai un NSLog() ogni volta che un messaggio viene inviato a un oggetto).Acquisizione di tutti i metodi/chiamate di messaggi su un oggetto

Penso che ricordo di averlo fatto prima ma ho dimenticato come. Sto pensando che potrebbe aiutarmi a rintracciare perché parte del mio codice non funziona.

risposta

18

È inoltre possibile utilizzare objective-c forwarding. Fondamentalmente è possibile creare un oggetto proxy che registra i metodi e quindi inoltra la chiamata all'originale. Vedere il mio blog post per maggiori dettagli.

@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

Ho appena provato questo e funziona in una certa misura. Sto provando con MKPinAnnotationView e si blocca con una NSInvalidArgumentException quando tenta di chiamare [MKPinAnnotationView superlayer]. Quindi ha provato a inviarlo a un oggetto che non ha questo metodo? –

+0

Il link del tuo blog post non è aggiornato. – mahboudz

0

È possibile utilizzare un oggetto NSProxy e sovrascrivere il metodo forwardInvocation:.

8

Il modo migliore per farlo è con dtrace o uno script di strumenti. Usando DTrace è possibile effettuare le seguenti operazioni:

Scrivi il seguente script come objc-calls.d

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

Quindi eseguire l'applicazione utilizzando lo script:

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

Si può anche costruire un costume Strumento che utilizza una sonda dtrace simile.

+0

Ho aggiunto un segnalibro al vostro aiuto, è utile, ma l'altro fornisce una soluzione più rapida/semplice. Grazie. – Jacob

1

Seguendo il commento di Louis Gerbarg dell'anno scorso, è anche utile poter filtrare facilmente in base al nome della classe.

provare il seguente script D:

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

salvarla, chmod a+x objc-calls.d, e poi fare sudo objc-calls.d -c /Your/Binary NSObject per vedere solo le invocazioni relativi alla NSObject (e le sue categorie).

Problemi correlati