iOS基于CocoaLumberjack的日志工具
使用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");
快快试一下吧~