iOS中日志同步获取NSLog重定向以及其他详解

2020-01-21 03:11:26王冬梅

使用以上方法的好处是不会影响Xcode控制台的输出,可以用非侵入性的方式来读取日志。

NSLog重定向

另一种方式就是重定向NSLog,这样NSLog就不会写到系统的syslog中了。

dup2重定向

通过重定向,可以直接截取stdout,stderr等标准输出的信息,然后保存在想要存储的位置,上传到服务器或者显示到View上。

要做到重定向,需要通过NSPipe创建一个管道,pipe有读端和写端,然后通过dup2将标准输入重定向到pipe的写端。再通过NSFileHandle监听pipe的读端,最后再处理读出的信息。

之后通过printf或者NSLog写数据,都会写到pipe的写端,同时pipe会将这些数据直接传送到读端,最后通过NSFileHandle的监控函数取出这些数据。

核心代码如下:


- (void)redirectStandardOutput{
 //记录标准输出及错误流原始文件描述符
 self.outFd = dup(STDOUT_FILENO);
 self.errFd = dup(STDERR_FILENO);
#if BETA_BUILD
 stdout->_flags = 10;
 NSPipe *outPipe = [NSPipe pipe];
 NSFileHandle *pipeOutHandle = [outPipe fileHandleForReading];
 dup2([[outPipe fileHandleForWriting] fileDescriptor], STDOUT_FILENO);
 [pipeOutHandle readInBackgroundAndNotify];
 stderr->_flags = 10;
 NSPipe *errPipe = [NSPipe pipe];
 NSFileHandle *pipeErrHandle = [errPipe fileHandleForReading];
 dup2([[errPipe fileHandleForWriting] fileDescriptor], STDERR_FILENO);
 [pipeErrHandle readInBackgroundAndNotify];
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(redirectOutNotificationHandle:) name:NSFileHandleReadCompletionNotification object:pipeOutHandle];
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(redirectErrNotificationHandle:) name:NSFileHandleReadCompletionNotification object:pipeErrHandle];
#endif
}
-(void)recoverStandardOutput{
#if BETA_BUILD
 dup2(self.outFd, STDOUT_FILENO);
 dup2(self.errFd, STDERR_FILENO);
 [[NSNotificationCenter defaultCenter] removeObserver:self];
#endif
}
// 重定向之后的NSLog输出
- (void)redirectOutNotificationHandle:(NSNotification *)nf{
#if BETA_BUILD
 NSData *data = [[nf userInfo] objectForKey:NSFileHandleNotificationDataItem];
 NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
 // YOUR CODE HERE... 保存日志并上传或展示
#endif
 [[nf object] readInBackgroundAndNotify];
}
// 重定向之后的错误输出
- (void)redirectErrNotificationHandle:(NSNotification *)nf{
#if BETA_BUILD
 NSData *data = [[nf userInfo] objectForKey:NSFileHandleNotificationDataItem];
 NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
 // YOUR CODE HERE... 保存日志并上传或展示
#endif
 [[nf object] readInBackgroundAndNotify];
}

文件重定向

另一种重定向的方式是利用c语言的freopen函数进行重定向,将写往stderr的内容重定向到我们制定的文件中去,一旦执行了上述代码那么在这个之后的NSLog将不会在控制台显示了,会直接输出在指定的文件中。