ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

CocoaLumberjack 彩色日志指南:用 DDTTYLogger 与 XcodeColors 实现分级着色输出

CocoaLumberjack 彩色日志指南:用 DDTTYLogger 与 XcodeColors 实现分级着色输出 CocoaLumberjack 彩色日志指南用 DDTTYLogger 与 XcodeColors 实现分级着色输出【免费下载链接】CocoaLumberjackA fast simple, yet powerful flexible logging framework for macOS, iOS, tvOS, watchOS and visionOS项目地址: https://gitcode.com/gh_mirrors/co/CocoaLumberjack本指南讲解如何在 CocoaLumberjack 中通过DDTTYLogger与 XcodeColors 插件让 Xcode 调试控制台与终端里的日志按级别、按上下文甚至按自定义标签显示不同颜色。读完本文你将掌握插件的安装、一行代码开启彩色输出的方法、前景色/背景色自定义方案、iOS 模拟器与真机调试的排查技巧以及底层颜色检测与映射的实现原理。CocoaLumberjack 面向 macOS、iOS、tvOS、watchOS 与 visionOSDDTTYLogger是其内置的「终端 / Xcode 控制台」日志记录器logger。默认情况下 Xcode 的控制台并不原生支持颜色而DDTTYLogger通过两个渠道解决着色问题在 Xcode 中借助XcodeColors插件在终端Terminal中则直接输出 ANSI 转义序列并自动映射到终端支持的颜色。本文所有示例均可直接运行仓库中同时提供了 Desktop 版 与 Mobile 版 的完整 Demo 工程供对照。为什么需要彩色日志当错误、警告、普通信息混在一起输出时靠肉眼在大量日志里分辨级别非常低效。给日志按级别配色后错误信息会以醒目的红色跳出来警告以橙色呈现其余信息保持默认颜色排查问题的效率会明显提升。技术背景是Xcode 调试控制台本身不支持颜色渲染直接向 stderr 写入 ANSI 颜色码只会显示成一段乱码。这正是 CocoaLumberjack 需要借助 XcodeColors 插件的原因——只有插件在控制台里解析并渲染颜色彩色日志才能正常工作。相关说明可见 DDTTYLogger 实现源码 开头的注释。第一步安装 XcodeColors 插件XcodeColors 是一个简单的 Xcode 插件作用就是让 Xcode 调试控制台支持颜色。安装过程概括为三步下载插件将插件放入 Xcode 的 Plug-ins 目录重启 Xcode。重启后 XcodeColors 会在 Xcode 启动时被自动加载并设置环境变量XcodeColors为YES。这个环境变量正是 CocoaLumberjack 判断当前是否处于 XcodeColors 环境中的唯一依据后续章节会详细展开它的作用。第二步启用彩色日志在标准的DDTTYLogger初始化代码之上只需要多一行代码即可开启颜色// Standard lumberjack initialization [DDLog addLogger:[DDTTYLogger sharedInstance]]; // And we also enable colors [[DDTTYLogger sharedInstance] setColorsEnabled:YES];colorsEnabled属性的默认值是NO见 DDTTYLogger 头文件。从源码看setColorsEnabled:内部通过 CocoaLumberjack 的日志队列异步更新开关并且在_colorProfilesArray为空时会自动加载默认配色方案实现位置。默认配色方案如果不做任何自定义默认配色为DDLogError红色DDLogWarn橙色这两个默认值同样可以在源码中直接找到loadDefaultColorProfiles为DDLogFlagError注册了 RGB(214, 57, 30) 的红色为DDLogFlagWarning注册了 RGB(204, 121, 32) 的橙色见 DDTTYLogger.m。第三步完全自定义颜色默认方案只是起点你可以对配色做完全自定义既可以分别指定前景色文字颜色和背景色也可以使用任意 RGB 数值。下面的例子把DDLogInfo级别的日志染成粉色// Lets customize our colors. // DDLogInfo : Pink #if TARGET_OS_IPHONE UIColor *pink [UIColor colorWithRed:(255/255.0) green:(58/255.0) blue:(159/255.0) alpha:1.0]; #else NSColor *pink [NSColor colorWithCalibratedRed:(255/255.0) green:(58/255.0) blue:(159/255.0) alpha:1.0]; #endif [[DDTTYLogger sharedInstance] setForegroundColor:pink backgroundColor:nil forFlag:DDLogFlagInfo]; DDLogInfo(Warming up printer); // Prints in Pink !注意其中用#if TARGET_OS_IPHONE区分了平台iOS 侧使用UIColormacOS 侧使用NSColor。在源码层面DDTTYLogger通过宏DDColor统一了两种颜色类型DDTTYLogger.hiOS/tvOS/watchOS 下DDColor即UIColormacOS 有 AppKit 时即NSColor纯命令行DD_CLI场景则使用CLIColor见 CLIColor.h。backgroundColor:参数传入nil表示不设置背景色如需背景色同样传入任意UIColor/NSColor即可。容易踩的坑传的是 Flag不是 Level自定义配色 API 接收的是Flag标志位而非Level级别这是文档中特别强调的陷阱GOOD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:DDLogFlagInfo]; // - Good :) BAD : [ttyLogger setForegroundColor:pink backgroundColor:nil forFlag:DDLogLevelInfo]; // - BAD! :(原因在于二者位掩码的语义完全不同DDLogFlagInfo 0...00100只有一位精确匹配某一个标志DDLogLevelInfo 0...00111包含 Info、Warning、Error 三个位如果误传DDLogLevelInfo实际会同时命中DDLogFlagInfo、DDLogFlagWarning和DDLogFlagError导致三个级别都被染成同一种颜色。这一点在 头文件注释 中有明确警告查阅 API 时务必留意。按上下文Context着色如果不同日志来源例如第三方框架使用了不同的日志上下文你可以按 context 精确着色LOG_CONTEXT_ALL定义为INT_MAX用于为所有未单独指定颜色的上下文设置默认色- (void)setForegroundColor:(nullable DDColor *)txtColor backgroundColor:(nullable DDColor *)bgColor forFlag:(DDLogFlag)mask context:(NSInteger)ctxt;关于 logging context 的更多用法可参考仓库文档 Documentation/CustomContext.md。按标签Tag着色更进一步DDTTYLogger还支持把某个DDLogMessage的 tag 直接映射到一个颜色档案从而做出一个纯色 NSLog 替代品。头文件中给出了完整示例DDTTYLogger.hstatic NSString *const PurpleTag PurpleTag; #define DDLogPurple(frmt, ...) LOG_OBJC_TAG_MACRO(NO, 0, 0, 0, PurpleTag, frmt, ##__VA_ARGS__) // 在配置 CocoaLumberjack 的地方 // purple 可以是 UIColor/NSColorCLI 工程用 CLIColor [[DDTTYLogger sharedInstance] setForegroundColor:purple backgroundColor:nil forTag:PurpleTag]; [DDLog addLogger:[DDTTYLogger sharedInstance]]; DDLogPurple(Im a purple log message!);清除颜色配置仓库还提供了一组清理 APIDDTTYLogger.h可用于动态调整配色- (void)clearColorsForFlag:(DDLogFlag)mask; - (void)clearColorsForFlag:(DDLogFlag)mask context:(NSInteger)context; - (void)clearColorsForTag:(id NSCopying)tag; - (void)clearColorsForAllFlags; - (void)clearColorsForAllTags; - (void)clearAllColors;iOS 模拟器与真机调试的颜色问题在 iOS 开发中你可能会遇到两类现象在模拟器里调试时颜色偶尔不生效在真机上调试时颜色从未生效。解决办法只需几秒钟在 Xcode 中打开 Scheme Editor菜单 Product - Edit Scheme...左侧选择 Run切到 Arguments 标签页添加一个名为XcodeColors、值为YES的环境变量。完成之后模拟器和真机上的颜色就能每次必现。仓库中的 Mobile Demo 甚至会在界面上直接检测并显示当前XcodeColors环境变量的状态XcodeColors enabled / disabled / not detected方便你确认设置是否生效。原理环境变量才是关键为什么这个环境变量如此重要源码中的检测逻辑解释了一切。在DDTTYLogger单例初始化时会读取两个环境变量DDTTYLogger.m__auto_type xcodeColors getenv(XcodeColors); __auto_type term getenv(TERM); if (xcodeColors (strcmp(xcodeColors, YES) 0)) { isaXcodeColorTTY YES; } else if (term) { if (strcasestr(term, color) ! NULL) { isaColorTTY YES; isaColor256TTY (strcasestr(term, 256) ! NULL); ... } }整个机制可以概括为一条链路XcodeColors 插件被 Xcode 启动时自动加载并设置环境变量XcodeColorsYESCocoaLumberjack 正是靠读取这个环境变量来判断XcodeColors 是否已安装。因为如果 XcodeColors 未安装而DDTTYLogger仍然注入颜色信息日志语句里就会出现一堆乱码字符Xcode 启动的任何子进程都会继承 Xcode 的环境变量。所以当你点击 Build-and-Run、由 Xcode 自动拉起模拟器时模拟器进程继承了XcodeColorsYES颜色正常但如果你手动启动模拟器此时模拟器并非 Xcode 的子进程不会继承该环境变量颜色就失效了真机调试同理。手动在 Scheme 的 Run 配置里添加XcodeColorsYES正是为了让任何启动方式下的调试会话都具备这个环境变量从而保证每次必现。在终端中使用彩色日志DDTTYLogger不仅支持 Xcode 控制台同样支持终端里的颜色输出。如果你在 Terminal 中调试命令行程序只要 shell 支持颜色DDTTYLogger就会自动把你配置的 RGB 颜色映射为 shell 支持的最接近的颜色。绝大多数情况下终端是xterm-256color支持 256 色因此任何你配置的 RGB 值都能找到相当接近的匹配色。源码层面终端着色走的是标准 ANSI 转义序列方案16 色模式initializeColors16内置了标准 Terminal.app 与 xterm 两套 16 色调色板通过MAP_TO_TERMINAL_APP_COLORS宏切换DDTTYLogger.m256 色模式initializeColors256内置了 216 个彩色色块与 24 级灰阶。注意 Apple Terminal.app 与标准 xterm 的 RGB 值并不一致所以源码中为 Terminal.app 手工维护了一张完整的 256 色表DDTTYLogger.m颜色匹配算法codeIndexForColor:遍历已知色板用欧氏距离RGB 空间的三维距离找出与目标颜色最接近的色号DDTTYLogger.m。源码纵深颜色是如何写入控制台的理解了在哪里检测再来看如何输出。DDTTYLoggerColorProfile是颜色档案的内部数据结构记录了mask日志标志、context上下文以及前景/背景的 RGB 值与对应的转义码DDTTYLogger.m。在logMessage:中着色流程分为三步DDTTYLogger.m查找颜色档案若_colorsEnabled开启先按_representedObject即 tag查字典未命中则遍历颜色档案数组按flag mask与 context 匹配LOG_CONTEXT_ALL作为兜底默认值匹配时不会提前 break以继续寻找更精确的 context 配置生成转义序列在DDTTYLoggerColorProfile初始化时XcodeColors 环境下用\033[fgR,G,B;/\033[bgR,G,B;格式生成前景/背景码宏XCODE_COLORS_ESCAPE_SEQ定义于 DDTTYLogger.m终端环境下则用映射得到的 ANSI 码如38;5;Nm重置码在 XcodeColors 下是\033[;在终端下是\033[0mDDTTYLogger.m高效写出使用writev(STDERR_FILENO, ...)一次性将前景码 背景码 消息 重置码以及时间戳、进程名、线程 ID 等 NSLog 风格前缀拼装写入 stderr避免多次系统调用带来的性能开销。这正是 XcodeColors.md 中未安装插件时注入颜色信息会产生乱码这一警告的根源转义序列只在能解析它的目标插件控制台或支持 ANSI 的终端中才被渲染为颜色。实战跑一遍仓库自带的 TestXcodeColors 示例仓库的 Demos/TestXcodeColors 目录同时提供了 Desktop 与 Mobile 两个演示工程完整展示了本文提到的全部能力开启颜色并打印默认配色Error 红 / Warn 橙将DDLogInfo自定义为粉色RGB 255,58,159将DDLogVerbose自定义为灰色通过 tag 实现纯色输出定义一个PurpleTag用DDLogPurple宏打印紫色日志Desktop 示例移动版还会读取XcodeColors环境变量并在界面上显示当前状态Mobile 示例。对照 XcodeColors.md 阅读这两个工程的AppDelegate可以快速验证默认配色是什么、自定义配色 API 的传参写法、以及 tag 着色的宏定义方式。注意 Mobile 工程需要在 Scheme 的 Run 参数中加入XcodeColorsYES环境变量才能看到彩色效果。总结与最佳实践三步开启彩色日志安装 XcodeColors 插件 →[DDTTYLogger sharedInstance]注册 logger →setColorsEnabled:YES默认配色Error 红、Warn 橙无需额外配置自定义配色使用setForegroundColor:backgroundColor:forFlag:传入DDLogFlag*记住是 Flag 不是 Level可同时设置前景色与背景色、任意 RGB 值还可按 context 或 tag 细分iOS 调试在 Scheme 的 Run Arguments 中配置环境变量XcodeColorsYES确保模拟器与真机每次都能继承该变量颜色稳定生效终端场景无需插件DDTTYLogger会自动按终端能力16 色 / 256 色将 RGB 映射到最接近的颜色。彩色日志是让日志一眼可扫的有效手段配合 CustomFormatters.md 中介绍的自定义格式化器可以把 Xcode 控制台打造成真正易读、易排查的调试窗口。【免费下载链接】CocoaLumberjackA fast simple, yet powerful flexible logging framework for macOS, iOS, tvOS, watchOS and visionOS项目地址: https://gitcode.com/gh_mirrors/co/CocoaLumberjack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表