オブジェクトに「フック」を設定して、どのメッセージがオブジェクトに送信されているかを確認するにはどうすればよいですか?(つまり、メッセージがオブジェクトに送信されるたびにNSLog()を実行します)。
以前にこれが行われたのを見たことを思い出すと思いますが、その方法を忘れています。コードの一部が機能しない理由を突き止めるのに役立つかもしれないと思っています。
オブジェクトに「フック」を設定して、どのメッセージがオブジェクトに送信されているかを確認するにはどうすればよいですか?(つまり、メッセージがオブジェクトに送信されるたびにNSLog()を実行します)。
以前にこれが行われたのを見たことを思い出すと思いますが、その方法を忘れています。コードの一部が機能しない理由を突き止めるのに役立つかもしれないと思っています。
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
これを行う最良の方法は、dtraceまたはinstrumentsスクリプトを使用することです。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プローブを使用してカスタム機器を構築することもできます。
昨年のLouisGerbargのコメントに続いて、クラス名で簡単にフィルタリングできることも便利です。
次の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(およびそのカテゴリ)に関連する呼び出しのみを表示します。
オブジェクトを使用して、メソッドNSProxy
をオーバーライドできます。forwardInvocation: