You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Swift中为CocoaLumberJack实现自定义日志级别?

Swift环境下CocoaLumberjack自定义日志级别方案

核心思路

绕开库预定义的DDLogLevel枚举限制,基于可自由扩展的DDLogFlag实现自定义级别,自己封装打印入口和过滤逻辑,不需要修改库源码或者添加OC桥接代码。

具体实现步骤

1. 定义自定义日志常量

首先扩展DDLogFlag定义你需要的6个级别对应的标记,同时定义对应的级别名称和开启组合:

import CocoaLumberjack

extension DDLogFlag {
    // 按权重从低到高定义6个自定义flag,每一个对应2的n次方
    static let verbose = Self(rawValue: 1 << 0)
    static let debug = Self(rawValue: 1 << 1)
    static let info = Self(rawValue: 1 << 2)
    static let warn = Self(rawValue: 1 << 3)
    static let error = Self(rawValue: 1 << 4)
    static let fatal = Self(rawValue: 1 << 5) // 新增的第6个级别
}

// 自定义日志级别组合,对应你需要开启的日志范围
struct CustomLogLevel {
    static let off: UInt = 0
    static let fatal: UInt = UInt(DDLogFlag.fatal.rawValue)
    static let error: UInt = fatal | UInt(DDLogFlag.error.rawValue)
    static let warn: UInt = error | UInt(DDLogFlag.warn.rawValue)
    static let info: UInt = warn | UInt(DDLogFlag.info.rawValue)
    static let debug: UInt = info | UInt(DDLogFlag.debug.rawValue)
    static let verbose: UInt = debug | UInt(DDLogFlag.verbose.rawValue)
    static let all: UInt = UInt.max
}

// 级别对应名称映射
private let logFlagNames: [DDLogFlag: String] = [
    .verbose: "VERBOSE",
    .debug: "DEBUG",
    .info: "INFO",
    .warn: "WARN",
    .error: "ERROR",
    .fatal: "FATAL"
]

2. 封装自定义打印入口

绕过库自带的打印宏,直接调用底层DDLog的日志提交方法,避免DDLogLevel枚举校验报错:

// 全局当前开启的日志级别,可动态修改
var currentLogLevel: UInt = CustomLogLevel.debug

func Log(
    _ message: @autoclosure () -> String,
    flag: DDLogFlag,
    file: StaticString = #file,
    function: StaticString = #function,
    line: UInt = #line
) {
    // 先做级别过滤,符合条件才提交日志
    guard currentLogLevel & flag.rawValue != 0 else { return }
    // 构造日志消息,level直接传flag对应的rawValue,不需要匹配预定义枚举
    let logMsg = DDLogMessage(
        message: message(),
        level: DDLogLevel(rawValue: flag.rawValue) ?? .off,
        flag: flag,
        context: 0,
        file: String(describing: file),
        function: String(describing: function),
        line: line,
        tag: nil,
        options: .copyFile,
        timestamp: nil
    )
    // 提交到DDLog,致命级别日志同步打印保证输出
    DDLog.sharedInstance.log(asynchronous: flag != .fatal, message: logMsg)
}

// 封装各个级别的快捷调用方法
func LogV(_ message: @autoclosure () -> String) { Log(message(), flag: .verbose) }
func LogD(_ message: @autoclosure () -> String) { Log(message(), flag: .debug) }
func LogI(_ message: @autoclosure () -> String) { Log(message(), flag: .info) }
func LogW(_ message: @autoclosure () -> String) { Log(message(), flag: .warn) }
func LogE(_ message: @autoclosure () -> String) { Log(message(), flag: .error) }
func LogF(_ message: @autoclosure () -> String) { Log(message(), flag: .fatal) }

3. 自定义日志格式器输出自定义级别名称

如果需要输出你自定义的级别名,需要实现自己的格式器:

class CustomLogFormatter: NSObject, DDLogFormatter {
    func format(message logMessage: DDLogMessage) -> String? {
        let levelName = logFlagNames[logMessage.flag] ?? "UNKNOWN"
        return "\(levelName): \(logMessage.message) [\(logMessage.fileName):\(logMessage.line) \(logMessage.function ?? "")]"
    }
}

// 配置logger的时候指定格式器即可
let consoleLogger = DDOSLogger.sharedInstance
consoleLogger.logFormatter = CustomLogFormatter()
DDLog.add(consoleLogger)

注意事项

  • 该方案不需要修改CocoaLumberjack的源码,也不需要额外写OC桥接代码,完全兼容Swift原生实现
  • 如果需要多个日志上下文,可以扩展context参数区分不同业务模块的日志级别

内容的提问来源于stack exchange,提问作者nhgrif

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 13:36:04