CocoaLumberjack是一个很好用的日志打印工具,它可以帮助我们把工程中的日志信息打印到终端或者输出到文件中。
地址:https://github.com/CocoaLumberjack/CocoaLumberjack
类图:
一:插件的运用
因为网上已经对CocoaLumberjack的运用都有很详细的介绍,有部分内容整理源自于网络结合项目中的运用进行讲解;
1.1:DDLog输出的类型
DDLog:基础类,必须引入的。
DDASLLogger:支持将调试语句写入到苹果的日志中。一般正对Mac开发。可选。
DDTTYLogger:支持将调试语句写入xCode控制台。我们即使要用它。可选。
DDFileLogger:支持将调试语句写入到文件系统。可选。
1.2: DDLog日志等级种类
DDLogError:定义输出错误文本
DDLogWarn:定义输出警告文本
DDLogInfo:定义输出信息文本
DDLogDebug:定义输出调试文本
DDLogVerbose:定义输出详细文本
提供的日志级别为:
LOG_LEVEL_ERROR:只显示错误日志。
LOG_LEVEL_WARN:包括:LOG_LEVEL_ERROR
LOG_LEVEL_INFO:包括:LOG_LEVEL_WARN
LOG_LEVEL_DEBUG:包括:LOG_LEVEL_INFO
LOG_LEVEL_VERBOSE:包括:LOG_LEVEL_DEBUG
LOG_LEVEL_OFF:关闭日志
1.3: 设置不同等级颜色
[[DDTTYLogger sharedInstance] setColorsEnabled:YES];// 启用颜色区分 [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor whiteColor] backgroundColor:[UIColor grayColor] forFlag:DDLogFlagVerbose]; //设置文字为白色,背景为灰色。 [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor redColor] backgroundColor:[UIColor whiteColor] forFlag:DDLogFlagDebug]; [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor cyanColor] backgroundColor:[UIColor blueColor] forFlag:DDLogFlagInfo]; [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor lightGrayColor] backgroundColor:[UIColor orangeColor] forFlag:DDLogFlagWarning]; [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor whiteColor] backgroundColor:[UIColor redColor] forFlag:DDLogFlagError];
注意:显示颜色是指针对XCode控制台的输出显示,还要结合插件XcodeColors(地址:https://github.com/robbiehanson/XcodeColors);然后要增加如下的setenv代码,它的位置放在上面,否则将没有效果;
setenv("XcodeColors", "YES", 0); [DDLog addLogger:[DDTTYLogger sharedInstance]];
1.4:设置输出日志的格式
因为在输出时我们希望获得更多的信息,DDLog可以自定义设置一个格式,从而获得日志详细信息;下面这个类是我们项目中运用:
ZULoggerFormatter* formatter = [[ZULoggerFormatter alloc] init]; [[DDTTYLogger sharedInstance] setLogFormatter:formatter]; //目前是在DDTTYLogger类型上显示,也可以加到输入到文件时
格式类:ZULoggerFormatter
@interface ZULoggerFormatter: NSObject<DDLogFormatter> @end #import "ZULoggerFormatter.h" #import "NSDate+Utilities.h" @implementation ZULoggerFormatter { } - (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; default: logLevel = @"[VBOSE]"; break; } NSString *formatStr = [NSString stringWithFormat:@"%@ %@ [%@][line %ld] %@ %@", logLevel, [logMessage.timestamp stringWithFormat:@"yyyy-MM-dd HH:mm:ss.S"], logMessage.fileName, logMessage.line, logMessage.function, logMessage.message]; return formatStr; } @end
1.5 设置宏取代NSLog
#if Product || Local #define NSLog(...) DDLogVerbose(__VA_ARGS__) #define Log(...) DDLogVerbose(__VA_ARGS__) #else #define NSLog(...) {} #define Log(...) {} #endif #define LogError(...) DDLogError(__VA_ARGS__)
这样就可以把项目中那些NSLog也替换成DDLogVerbose级别的错误;
1.6 设置不同环境输出日志等级
#if Product ||Local static const int ddLogLevel = LOG_LEVEL_VERBOSE; #else static const int ddLogLevel = LOG_LEVEL_ERROR; #endif
1.7 设置输出到文件
- (DDFileLogger *)fileLogger { if (!_fileLogger) { DDFileLogger *fileLogger = [[DDFileLogger alloc] init]; fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling fileLogger.logFileManager.maximumNumberOfLogFiles = 7; _fileLogger = fileLogger; } return _fileLogger; }
如果没有设置,它是有提供相应的默认值:
unsigned long long const kDDDefaultLogMaxFileSize = 1024 * 1024; // 1 MB 一个文件大小 NSTimeInterval const kDDDefaultLogRollingFrequency = 60 * 60 * 24; // 24 Hours 一天 NSUInteger const kDDDefaultLogMaxNumLogFiles = 5; // 5 Files 五个 unsigned long long const kDDDefaultLogFilesDiskQuota = 20 * 1024 * 1024; // 20 MB 总共
如果有存储路径(可以设置paths):
NSString *appName = [[NSProcessInfo processInfo] processName]; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); NSString *basePath = ([paths count] > 0) ? paths[0] : NSTemporaryDirectory(); NSString *logsDirectory = [[basePath stringByAppendingPathComponent:@"Logs"] stringByAppendingPathComponent:appName];
1.8 分享项目用到的日志管理类
#import <Foundation/Foundation.h> #import <CocoaLumberjack.h> #import "ZULoggerFormatter.h" @interface MyFileLogger : NSObject @property (nonatomic, strong, readwrite) DDFileLogger *fileLogger; +(MyFileLogger *)sharedManager; @end #import "MyFileLogger.h" @implementation MyFileLogger #pragma mark - Inititlization - (instancetype)init { self = [super init]; if (self) { [self configureLogging]; } return self; } #pragma mark 单例模式 static MyFileLogger *sharedManager=nil; +(MyFileLogger *)sharedManager { static dispatch_once_t once; dispatch_once(&once, ^{ sharedManager=[[self alloc]init]; }); return sharedManager; } #pragma mark - Configuration - (void)configureLogging { setenv("XcodeColors", "YES", 0); [DDLog addLogger:[DDASLLogger sharedInstance]]; [DDLog addLogger:[DDTTYLogger sharedInstance]]; [[DDTTYLogger sharedInstance] setColorsEnabled:YES]; [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor blueColor] backgroundColor:nil forFlag:DDLogFlagInfo]; [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor purpleColor] backgroundColor:nil forFlag:DDLogFlagDebug]; [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor redColor] backgroundColor:nil forFlag:DDLogFlagError]; [[DDTTYLogger sharedInstance] setForegroundColor:[UIColor greenColor] backgroundColor:nil forFlag:DDLogFlagVerbose]; ZULoggerFormatter* formatter = [[ZULoggerFormatter alloc] init]; [[DDTTYLogger sharedInstance] setLogFormatter:formatter]; [DDLog addLogger:self.fileLogger]; } #pragma mark - Getters - (DDFileLogger *)fileLogger { if (!_fileLogger) { DDFileLogger *fileLogger = [[DDFileLogger alloc] init]; fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling fileLogger.logFileManager.maximumNumberOfLogFiles = 7; _fileLogger = fileLogger; } return _fileLogger; } @end
二:知识点
2.1 关于等级包含的设置,DDLogLevelAll显示所有,基它则依次降底跟相互包含;可以通过这个代码了解到枚举的设置;
typedef NS_OPTIONS(NSUInteger, DDLogFlag){ /** * 0...00001 DDLogFlagError */ DDLogFlagError = (1 << 0), /** * 0...00010 DDLogFlagWarning */ DDLogFlagWarning = (1 << 1), /** * 0...00100 DDLogFlagInfo */ DDLogFlagInfo = (1 << 2), /** * 0...01000 DDLogFlagDebug */ DDLogFlagDebug = (1 << 3), /** * 0...10000 DDLogFlagVerbose */ DDLogFlagVerbose = (1 << 4) }; /** * Log levels are used to filter out logs. Used together with flags. */ typedef NS_ENUM(NSUInteger, DDLogLevel){ /** * No logs */ DDLogLevelOff = 0, /** * Error logs only */ DDLogLevelError = (DDLogFlagError), /** * Error and warning logs */ DDLogLevelWarning = (DDLogLevelError | DDLogFlagWarning), /** * Error, warning and info logs */ DDLogLevelInfo = (DDLogLevelWarning | DDLogFlagInfo), /** * Error, warning, info and debug logs */ DDLogLevelDebug = (DDLogLevelInfo | DDLogFlagDebug), /** * Error, warning, info, debug and verbose logs */ DDLogLevelVerbose = (DDLogLevelDebug | DDLogFlagVerbose), /** * All logs (1...11111) */ DDLogLevelAll = NSUIntegerMax };
增加相应的宏进行处理
#define NSLogError(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 1) NSLog((frmt), ##__VA_ARGS__); } while(0) #define NSLogWarn(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 2) NSLog((frmt), ##__VA_ARGS__); } while(0) #define NSLogInfo(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 3) NSLog((frmt), ##__VA_ARGS__); } while(0) #define NSLogDebug(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 4) NSLog((frmt), ##__VA_ARGS__); } while(0) #define NSLogVerbose(frmt, ...) do{ if(DD_NSLOG_LEVEL >= 5) NSLog((frmt), ##__VA_ARGS__); } while(0)
2.2:进程类NSProcessInfo方法
+(NSProcessInfo*)processInfo //返回当前进程的信息 -(NSArray*)arguments //以NSString对象数组的形式返回当前进程的参数 -(NSDictionary *)environment //返回变量/值对词典,以描述当前的环境变量(比如PATH和HOME)及其值 -(int)processIdentifier //返回进程标识符,它是操作系统赋予进程的唯一数字,用于识别每个正在运行的进程 -(NSString*)processName //返回当前正在执行的进程名称 -(NSString *)globallyUniqueString //每次调用这个方法时,都返回不同的单值字符串,可以用这个字符串生成单值临时文件名 -(NSString *)hostname //返回主机系统的名称(在笔者的Mac OS x系统中,返回的是mac-mato-ipad.local) -(NSUInteger)operatingSystem //返回表示操作系统的数字(在笔者的Mac OS x系统中,返回的是5) -(NSString *)operatingSystemName //返回操作系统的名称(笔者的Mac OS x系统中返回NSMACHOperatingSystem,可能返回的值定义在NSProgressInfo.h文件中) -(NSString *)operatingSystemVersionString //返回操作系统的当前版本(笔者的Mac OS x系统中返回Version 10.7.5 (Build 11G56)) -(void)setProcessName:(NSString *)name //将当前进程名称设置为name。应该谨慎地使用这个方法,应为关于进程名称存在一些假设(比如用户默认的设置)
例如:
NSString *appName = [[NSProcessInfo processInfo] processName];
2.3: lengthOfBytesUsingEncoding:NSUTF8StringEncoding
用于计算含有中英文的字符串长度,包含一个中文字用上面的方法时会转化成三个字节,其它一个字节; int len = [textField.text lengthOfBytesUsingEncoding:NSUTF8StringEncoding];