有没有一种方法可以记录给定类的每个方法的每个调用?

3
我正在寻找一种方法来记录给定UIView的每个方法调用,以进行调试。
2个回答

5
这是我编写的代码:

链接

下面是使用的步骤:
  1. 通过从NSProxy子类化来创建代理类
  2. 在目标类上交换allocWithZone:,并用代理类包装返回的对象
  3. 在代理类的forwardInvocation:中记录消息

#import <objc/runtime.h>

@interface XLCProxy : NSProxy

+ (id)proxyWithObject:(id)obj;

@end

@implementation XLCProxy
{
    id _obj;
}

+ (void)load
{
    {
        Class cls = NSClassFromString(@"IDESourceCodeDocument");
        id metacls = object_getClass(cls);
        IMP imp = class_getMethodImplementation(metacls, @selector(allocWithZone:));
        IMP newimp = imp_implementationWithBlock(^id(id me, SEL cmd, NSZone *zone) {
            id obj = ((id (*)(id,SEL,NSZone*))(imp))(me, cmd, zone);
            return [XLCProxy proxyWithObject:obj];
        });
        BOOL success = class_addMethod(metacls, @selector(allocWithZone:), newimp, [[NSString stringWithFormat:@"@@:%s", @encode(NSZone*)] UTF8String]);
        if (!success) {
            NSLog(@"Add method failed");
        }
    }
}

+ (id)proxyWithObject:(id)obj
{
    XLCProxy *proxy = [self alloc];
    proxy->_obj = obj;
    return proxy;
}

- (void)forwardInvocation:(NSInvocation *)invocation
{
    const char *selname = sel_getName([invocation selector]);

    [invocation setTarget:_obj];
    [invocation invoke];

    if ([@(selname) hasPrefix:@"init"] && [[invocation methodSignature] methodReturnType][0] == '@') {
        const void * ret;
        [invocation getReturnValue:&ret];
        ret = CFBridgingRetain([XLCProxy proxyWithObject:_obj]);
        [invocation setReturnValue:&ret];
    }


    NSLog(@"%@ %s", [_obj class], selname);
//    if ([[invocation methodSignature] methodReturnType][0] == '@') {
//        NSObject __unsafe_unretained * obj;
//        [invocation getReturnValue:&obj];
//        NSLog(@"%@", obj);
//    }
}

-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    return [_obj methodSignatureForSelector:sel];
}

- (Class)class
{
    return [_obj class];
}

@end

3
您可以使用DTrace。这是一个一行代码的示例:
sudo dtrace -q -n 'objc$target:YourClass::entry { printf("%c[%s %s]\n", probefunc[0], probemod, probefunc + 1); }' -p <the PID of the target process>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接