6

如何在对象上放置一个“钩子”,以便我可以看到正在向它发送哪些消息?(即每次向对象发送消息时执行 NSLog())。

我想记得以前看过这个,但我忘记了怎么做的。我想它可能会帮助我找出为什么我的部分代码不起作用。

4

4 回答 4

18

您还可以使用objective-c 转发。基本上,您可以创建一个代理对象来记录方法,然后将调用转发给原始对象。有关更多详细信息,请参阅我的博客文章

@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
于 2009-08-25T13:30:20.520 回答
8

最好的方法是使用 dtrace 或仪器脚本。使用 dtrace,您可以执行以下操作:

将以下脚本编写为 objc-calls.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 探针构建自定义仪器。

于 2009-08-25T12:59:00.193 回答
1

继去年 Louis Gerbarg 的评论之后,能够轻松按类名进行过滤也很有用。

试试下面的 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(及其类别)相关的调用。

于 2010-09-30T22:39:04.977 回答
0

您可以使用一个NSProxy对象并覆盖该forwardInvocation:方法。

于 2009-08-25T12:26:10.683 回答