iOS调试篇(一)——日志重定向篇

1 CocoaLumberjack

使用开源第三方库CocoaLumberjack。

2 hook

使用fishhook来hook系统的NSLog方法,具体原理及方法可见:Fishhook 学习笔记
(注意fishhook只能hook系统的c方法,自定义的不行,原理还是见上面的Fishhook学习笔记)

#import "ViewController.h"
#import "fishhook.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //定义rebinding 结构体
    struct rebinding rebind = {};
    rebind.name = "NSLog";
    rebind.replacement = hookNSLog;
    rebind.replaced = (void *)&nslogMethod;

    //将上面的结构体 放入 reb结构体数组中
    struct rebinding red[]  = {rebind};

    /*
     * arg1 : 结构体数据组
     * arg2 : 数组的长度
     */

    rebind_symbols(red, 1);
}

//定义一个函数指针 用于指向原来的NSLog函数
static void (*nslogMethod)(NSString *format, ...);

void hookNSLog(NSString *format, ...){
    
    format = [format stringByAppendingString:@"被勾住了"];
    
    nslogMethod(format);
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    NSLog(@"原有NSLog函数");
}

3 dup2 函数和 STDERR 句柄

NSLog 最后写文件时的句柄是 STDERR,我们可以通过重定向的方式将输出路径改变。参考: iOS日志获取和实时浏览器显示日志

#import "ViewController.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self redirectSTD:STDERR_FILENO];
}

- (void)redirectSTD:(int )fd{
    NSPipe * pipe = [NSPipe pipe] ;
    NSFileHandle *pipeReadHandle = [pipe fileHandleForReading] ;
    int pipeFileHandle = [[pipe fileHandleForWriting] fileDescriptor];
    dup2(pipeFileHandle, fd) ;
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(redirectNotificationHandle:)
                                                 name:NSFileHandleReadCompletionNotification
                                               object:pipeReadHandle] ;
    [pipeReadHandle readInBackgroundAndNotify];
}

- (void)redirectNotificationHandle:(NSNotification *)nf{
    NSData *data = [[nf userInfo] objectForKey:NSFileHandleNotificationDataItem];
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ;
    //这里可以做我们需要的操作,例如将nslog显示到一个textview中,或者是存放到另一个文件中等等
    //self.logTextView.text = [NSString stringWithFormat:@"%@\n%@",self.logTextView.text, str];
    NSRange range;
    //range.location = [self.logTextView.text length] - 1;
    range.length = 0;
    //[self.logTextView scrollRangeToVisible:range];
    
    [[nf object] readInBackgroundAndNotify];
}

4 参考文章

Fishhook 学习笔记
iOS日志获取和实时浏览器显示日志

你可能感兴趣的:(iOS调试篇(一)——日志重定向篇)