捕获对象上的所有方法/消息调用

发布于 2024-08-03 06:57:52 字数 121 浏览 5 评论 0原文

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

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

How do I put a "hook" on an object so I can see what messages are being sent to it? (ie do an NSLog() every time a message is sent to an object).

I think recall seeing this done before but I forget how. I am thinking it might help me track down why part of my code is not working.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

千寻… 2024-08-10 06:57:52

您还可以使用 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

You can also use objective-c forwarding. Basically you can create a proxy object that logs the methods then forwards the call to the original. See my blog post for more details.

@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
女皇必胜 2024-08-10 06:57:52

执行此操作的最佳方法是使用 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 探针构建自定义 Instrument。

The best way to do this is with dtrace or an instruments script. Using dtrace you can do the following:

Write the following script as objc-calls.d

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

Then run the app using the script:

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

You can also build a custom Instrument using a similiar dtrace probe.

不甘平庸 2024-08-10 06:57:52

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

Following up on Louis Gerbarg's comment from last year, it's also useful to be able to easily filter by class name.

Try the following D script:

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

Save it, chmod a+x objc-calls.d, and then do sudo objc-calls.d -c /Your/Binary NSObject to see just the invocations related to NSObject (and its categories).

娇柔作态 2024-08-10 06:57:52

您可以使用 NSProxy 对象并重写 forwardInitation: 方法。

You could use a NSProxy object and override the forwardInvocation: method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文