CocoaLumberJack是一个用于mac或者iOS的日志库,简单易用, 可扩展。
可以通过设置Logger,分别把日志写入文件、终端、系统日志中。
DDLogLevel   7个等级
库不大,代码结构比较清晰。
使用 我用的cocopods、oc。
修改podfile
1 2 3 4 // podfile  pod 'CocoaLumberjack' 
代码
1 2 3 4 5 6 7 8 9 #import <CocoaLumberjack/CocoaLumberjack.h> // 引用头文件 static DDLogLevel ddLogLevel = DDLogLevelAll; // 定义全局变量 ...     DDLogInfo(@"message"); ... 
代码解读 主要代码类可以参考GitHub给出的图。
DDLog 这个是对外的接口, 所有API都是直接调用这个接口的类方法进行写日志的。
有一个单例和一个队列。 所有写日志操作,最终都是在同一个队列进行操作的。 
日志可以写到不同的输出终端, 通过DDLogger协议来控制, DDLog可以添加多个DDLogger协议的对象(具体的都是抽象类DDAbstractLogger的子类)。
1 2 3 4 5 6 7 8 9 10 11 12 // _loggingQueue // _loggingGroup // _queueSemaphore // _numProcessors _loggingGroup 用于并发输出 UIApplicationWillTerminateNotification 执行 flushLog applicationWillTerminate 
DDLogMessage 日志信息 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 {     // Direct accessors to be used only for performance     @public     NSString *_message;  // 内容     DDLogLevel _level;      // 等级     DDLogFlag _flag;      // 用于过滤等级的信息, 只有   _level & _flag == 1 才会输出     NSInteger _context;     // 可以用来过滤, 参考 DDContextWhitelistFilterLogFormatter     NSString *_file;        // 输出文件路径     NSString *_fileName;    // 输出文件名     NSString *_function;    //  ??      NSUInteger _line;            id _tag;        // ??      DDLogMessageOptions _options;     NSDate *_timestamp;     NSString *_threadID;     NSString *_threadName;     NSString *_queueLabel; } 
_loggerQueue
DDAbstractLogger 抽象的logger, 
可以设置logFormatter、loggerQueue
logFormatter可以对输出的日志再格式化。
DDLoggerNode 用于记录logger的信息 1 2 3 4 5 6 7 8 9 10 11 12 @interface DDLoggerNode : NSObject {     // Direct accessors to be used only for performance     @public     id <DDLogger> _logger;     DDLogLevel _level;     dispatch_queue_t _loggerQueue; } @property (nonatomic, readonly) id <DDLogger> logger; @property (nonatomic, readonly) DDLogLevel level; @property (nonatomic, readonly) dispatch_queue_t loggerQueue; 
不同的logger输出, 又在各自的queue中操作。
DDLogger protocol 1 2 3 - (void)logMessage:(DDLogMessage *)logMessage NS_SWIFT_NAME(log(message:));   @property (nonatomic, strong) id <DDLogFormatter> logFormatter; 
DDTTYLogger 写到tty的logger
DDOSLogger usr/include/os/log.h
os_log_create
DDASLLogger asl.h // 废弃了, 使用 usr/include/os/log.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 _client = asl_open(NULL, "com.apple.console", 0); {         const char *msg = [message UTF8String];         size_t aslLogLevel;         switch (logMessage->_flag) {             // Note: By default ASL will filter anything above level 5 (Notice).             // So our mappings shouldn't go above that level.             case DDLogFlagError     : aslLogLevel = ASL_LEVEL_CRIT;     break;             case DDLogFlagWarning   : aslLogLevel = ASL_LEVEL_ERR;      break;             case DDLogFlagInfo      : aslLogLevel = ASL_LEVEL_WARNING;  break; // Regular NSLog's level             case DDLogFlagDebug     :             case DDLogFlagVerbose   :             default                 : aslLogLevel = ASL_LEVEL_NOTICE;   break;         }         static char const *const level_strings[] = { "0", "1", "2", "3", "4", "5", "6", "7" };         // NSLog uses the current euid to set the ASL_KEY_READ_UID.         uid_t const readUID = geteuid();         char readUIDString[16]; #ifndef NS_BLOCK_ASSERTIONS         size_t l = (size_t)snprintf(readUIDString, sizeof(readUIDString), "%d", readUID); #else         snprintf(readUIDString, sizeof(readUIDString), "%d", readUID); #endif         NSAssert(l < sizeof(readUIDString),                  @"Formatted euid is too long.");         NSAssert(aslLogLevel < (sizeof(level_strings) / sizeof(level_strings[0])),                  @"Unhandled ASL log level.");         aslmsg m = asl_new(ASL_TYPE_MSG);         if (m != NULL) {             if (asl_set(m, ASL_KEY_LEVEL, level_strings[aslLogLevel]) == 0 &&                 asl_set(m, ASL_KEY_MSG, msg) == 0 &&                 asl_set(m, ASL_KEY_READ_UID, readUIDString) == 0 &&                 asl_set(m, kDDASLKeyDDLog, kDDASLDDLogValue) == 0) {                 asl_send(_client, m);             }             asl_free(m);         }         //TODO handle asl_* failures non-silently?     } 
OS_OBJECT_USE_OBJC 用于判断系统是否是6.0以前的? 6.0之后才定义了这个宏。
 
dispatch_group_async
1 2 3 4 5 6 {     // Direct accessors to be used only for performance     @public     id <DDLogger> _logger;     DDLogLevel _level; } 
欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。