Перехват всех вызовов методов / сообщений на объекте - PullRequest
6 голосов
/ 25 августа 2009

Как мне поставить «крючок» на объект, чтобы я мог видеть, какие сообщения ему отправляются? (т.е. делать NSLog () каждый раз, когда сообщение отправляется объекту).

Я думаю, вспоминаю, как это уже делал, но я забыл как. Я думаю, что это может помочь мне отследить, почему часть моего кода не работает.

Ответы [ 4 ]

18 голосов
/ 25 августа 2009

Вы также можете использовать target-c forwarding . По сути, вы можете создать прокси-объект, который регистрирует методы, а затем перенаправляет вызов оригиналу. См. Мой пост в блоге для более подробной информации.

@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
8 голосов
/ 25 августа 2009

Лучший способ сделать это - использовать dtrace или скрипт инструментов. Используя dtrace, вы можете сделать следующее:

Напишите следующий скрипт как objc-Call.D

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

Затем запустите приложение, используя скрипт:

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

Вы также можете создать собственный инструмент, используя похожий зонд dtrace.

1 голос
/ 01 октября 2010

Следуя комментариям Луи Гербарга за прошлый год, также полезно иметь возможность легко фильтровать по имени класса.

Попробуйте следующий сценарий D:

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

Сохраните его, chmod a+x objc-calls.d, а затем выполните sudo objc-calls.d -c /Your/Binary NSObject, чтобы увидеть только вызовы, связанные с NSObject (и его категориями).

0 голосов
/ 25 августа 2009

Вы можете использовать объект NSProxy и переопределить метод forwardInvocation:.

...