iOS基于CocoaLumberjack的日志工具

作者: uniapp | 来源:发表于2018-01-19 23:37 被阅读42次

    使用Xcode编辑器进行iOS开发,其高效的便捷性和友好的开发体验,无可非议。我毫不怀疑:如果对所有程序猿开发的编辑器做一个排名的话,Xcode肯定能排上前几名。但是不得不说Xcode中的一个缺点是:打印日志不能分级。Android开发中可以对日志分为verbose,debug,error,warning,info等级别,这样能很方便的在编辑器中对日志信息进行过滤,定位问题更加方便。所以,「Ernesto Rivera」大神就开发出了CocoaLumberjack,可以方便的对日志进行分级。

    CocoaLumberjack (VS) NSLog 具有效率高、功能强大、便于拓展的诸多优点。CocoaLumberjack的基本使用,github上面写的很详细。可以通过Cocoapods或者将文件直接嵌入工程的方式来使用,可以同时实现在Xcode日志栏、App沙盒目录、iPhone线程三个地方输出日志。

    结合实际工程,最好的使用方式是:在CocoaLumberjack基础上,封装成自己的Log日志方式。这样做既可以保持工程编码风格的一致性,同时让工程代码与第三方依赖库隔离,防止以后依赖库没人维护时,顺利地替换成其他库。比如我们在iOS开发中,常常基于AFNetworking封装自己工程的网络请求。

    封装CocoaLumberjack很方便,因为CocoaLumberjack本身已经预留了拓展的接口DDDispatchQueueLogFormatter。新建类ZDLogFormatter继承自DDDispatchQueueLogFormatter,重写- (NSString *)formatLogMessage:(DDLogMessage *)logMessage方法定义日志的具体格式。

    @interface ZDLogFormatter : DDDispatchQueueLogFormatter
    
    @end
    
    @implementation ZDLogFormatter
    
    //日志具体格式
    - (NSString *)formatLogMessage:(DDLogMessage *)logMessage
    {
    
        NSString *logLevel = nil;
        switch (logMessage.flag)
        {
                
            case DDLogFlagError:
                logLevel = @"[ERROR] > ";
                break;
            case DDLogFlagWarning:
                logLevel = @"[WARN]  > ";
                break;
            case DDLogFlagInfo:
                logLevel = @"[INFO]  > ";
                break;
            case DDLogFlagDebug:
                logLevel = @"[DEBUG] > ";
                break;
            case DDLogFlagVerbose:
                logLevel = @"[VBOSE] > ";
                break;
            default:
                logLevel = @"[VBOSE] > ";
                break;
        }
        
        NSTimeZone *zone = [NSTimeZone systemTimeZone];
        NSInteger interval = [zone secondsFromGMTForDate:logMessage.timestamp];
        NSDate *localeDate = [logMessage.timestamp dateByAddingTimeInterval:interval];
        NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss:SSS"];
        NSString *formatStr = [NSString stringWithFormat:@"%@ %@[%@ %@][line %@][thread:%@]:\n%@",
                               [dateFormatter stringFromDate:localeDate],
                               logLevel,
                               logMessage.fileName,
                               logMessage.function,
                               @(logMessage.line),
                               [self queueThreadLabelForLogMessage:logMessage],
                               logMessage.message];
        return formatStr;
    }
    @end
    

    定义自己的日志工具类ZDLog,继承至NSObject。

    //.h文件
    #import "CocoaLumberjack.h"
    #import <Foundation/Foundation.h>
    
    #ifdef LOG_LEVEL_DEF
    #undef LOG_LEVEL_DEF
    #define LOG_LEVEL_DEF ZDLog_logLevel
    #endif
    
    #ifdef LOG_ASYNC_ENABLED
    #undef LOG_ASYNC_ENABLED
    #ifdef DEBUG
    #define LOG_ASYNC_ENABLED NO
    #else
    #define LOG_ASYNC_ENABLED YES
    #endif
    #endif
    
    typedef NS_ENUM(NSUInteger, ZDLogLevel)
    {
        ZDLogLevelOff = DDLogLevelOff,
        ZDLogLevelError = DDLogLevelError,
        ZDLogLevelWarning = DDLogLevelWarning,
        ZDLogLevelInfo = DDLogLevelInfo,
        ZDLogLevelDebug = DDLogLevelDebug,
        ZDLogLevelVerbose = DDLogLevelVerbose,
        ZDLogLevelAll = DDLogLevelAll
    };
    extern int ZDLog_logLevel;
    
    #define ZDLogError(frmt, ...)   DDLogError(frmt, ##__VA_ARGS__)
    #define ZDLogWarn(frmt, ...)    DDLogWarn(frmt, ##__VA_ARGS__)
    #define ZDLogInfo(frmt, ...)    DDLogInfo(frmt, ##__VA_ARGS__)
    #define ZDLogDebug(frmt, ...)   DDLogDebug(frmt, ##__VA_ARGS__)
    #define ZDLogVerbose(frmt, ...) DDLogVerbose(frmt, ##__VA_ARGS__)
    
    @interface ZDLog : NSObject
    /**
     *
     *  设置日志级别,必须设置,否则不打开日志
     *
     *  @param logLevel 级别,见枚举.
     */
    + (void)setLevel:(ZDLogLevel)logLevel;
    @end
    
    //.m文件
    #import "ZDLog.h"
    #import "DDDispatchQueueLogFormatter.h"
    #ifdef DEBUG
    int ZDLog_logLevel = ZDLogLevelVerbose;
    #else
    int ZDLog_logLevel = ZDLogLevelWarning;
    #endif
    
    @implementation ZDLog
    
    + (void)setLevel:(ZDLogLevel)logLevel
    {
        ZDLog_logLevel = (int)logLevel;
        [DDLog removeAllLoggers];
        [self addTTYLoggerWithLevel:(ZDLogLevel) logLevel];
        [self addFileLoggerWithLevel:(ZDLogLevel) logLevel];
        [self addASLLoggerWithLevel:(ZDLogLevel) logLevel];
    }
    //添加日志到iPhone后台线程
    + (void)addASLLoggerWithLevel:(ZDLogLevel)logLevel
    {
        DDASLLogger *logger = [DDASLLogger sharedInstance];
        logger.logFormatter = [[ZDLogFormatter alloc] init];
        [DDLog addLogger:logger withLevel:(DDLogLevel) logLevel];
    }
    //添加日志到Xcode打印区
    + (void)addTTYLoggerWithLevel:(ZDLogLevel)logLevel
    {
        DDTTYLogger *ttyLogger = [DDTTYLogger sharedInstance];
        ttyLogger.logFormatter = [[ZDLogFormatter alloc] init];
        [DDLog addLogger:ttyLogger withLevel:(DDLogLevel) logLevel];
    }
    //添加日志到App沙河目录
    + (void)addFileLoggerWithLevel:(ZDLogLevel)logLevel
    {
        DDFileLogger *fileLogger = [DDFileLogger new];
        fileLogger.logFileManager.maximumNumberOfLogFiles = 10;
        fileLogger.logFormatter = [[ZDLogFormatter alloc] init];
        [DDLog addLogger:fileLogger withLevel:(DDLogLevel) logLevel];
    }
    @end
    

    使用时,首先调用ZDLog的类方法setLevel定义需要显示的日志等级。这样在需要打印日志的地方,设置引入ZDLog的头文件,然后就可以调用ZDLog来打印日志了:

    ZDLogError(@"ZDLogError");
    ZDLogWarn(@"ZDLogWarn");
    ZDLogInfo(@"ZDLogInfo");
    ZDLogDebug(@"ZDLogDebug");
    ZDLogVerbose(@"ZDLogVerbose");
    

    快快试一下吧~

    关注和喜欢都是对我的鼓励和支持~

    相关文章

      网友评论

        本文标题:iOS基于CocoaLumberjack的日志工具

        本文链接:https://www.haomeiwen.com/subject/ttaaoxtx.html