如何在对象上放置一个“钩子”,这样我才能看到正在向它发送的消息? (即每次向对象发送消息时都要执行NSLog())。
我想回想一下之前就已经完成了这件事,但我忘记了。我想这可能有助于我找出部分代码无效的原因。
答案 0 :(得分:18)
您也可以使用objective-c forwarding。基本上,您可以创建一个记录方法的代理对象,然后将调用转发给原始方法。有关详细信息,请参阅我的blog post。
@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
答案 1 :(得分: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探针构建自定义仪器。
答案 2 :(得分: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(及其类别)相关的调用。
答案 3 :(得分:0)
您可以使用NSProxy
对象并覆盖forwardInvocation:
方法。