iOS开发之 NSLog 重定向

iOS开发 2018-03-27 已阅 3749 次

NSLog 重定向

不在控制台输出,而是定向到指定的地方统一处理。

为什么要对NSLog重定向

在开发中,我可能需要对日记保存,但在NSLog调用地方都调用保存操作,很不方便也不方便维护;当然你也可以使用第三方框架(比如CocoaLumberjack),但是你可能仅仅想保存日记这个操作,而不需要其他操作,并不想使用第三方框架,这时对NSLog重定向是一个很好的选择(毕竟习惯了NSLog)。

代码实现

我已封装成一个工具类,可以拿去使用。

Objective-C 版本

NSLogRedirect.h 代码

#import <Foundation/Foundation.h>

@interface NSLogRedirect : NSObject

+ (void)enableRedirect;

@end

NSLogRedirect.m 代码

#import "NSLogRedirect.h"

@implementation NSLogRedirect

/**
 在 application:didFinishLaunchingWithOptions: 方法中最先调用此方法即可对NSLog重定向
 */
+ (void)enableRedirect {
    
    static NSLogRedirect *sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        sharedInstance = [[NSLogRedirect alloc] init];
    });
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        
        [self redirectToPostNotification:STDERR_FILENO];
    }
    return self;
}

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

- (void)redirectNotificationHandle:(NSNotification *)notification {
    
    /** ==== 请不要在此函数中使用NSLog ====*/
    /** ==== 请不要在此函数中使用NSLog ====*/
    /** ==== 请不要在此函数中使用NSLog ====*/
    /** ==== 会导致死循环,会导致死循环,会导致死循环 ====*/
    
    NSData *data = [[notification userInfo] objectForKey:NSFileHandleNotificationDataItem];
    NSString *messageString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSArray<NSString *> *messages = [messageString componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"\n]"]];

    for (NSString *messageItem in messages) {
        
        if (!messageItem.length || [messageItem containsString:@"["]) {
            
            continue;
        }
        
        // 在此处理每一条log,messageItem为log的内容
        /** 比如:统一保存到指定文件中 */
        /** 比如:统一输出格式,使用printf打印出来 */
        /** ........... */
        printf("%s\n", messageItem.UTF8String);
    }

    [[notification object] readInBackgroundAndNotify];
}

- (void)dealloc {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

Swift 版本

comeing soon

本文由 Harvey 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论