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

Swift宏中OSLog无法保留原始文件/行号的解决方案咨询

Swift 宏实现调用处文件行号日志的解决方案

核心思路

Swift宏可以通过展开时注入调用上下文的#file、#line、#column,直接传递给日志函数,避免使用宏定义文件的元数据。关键是让宏在代码展开阶段,就把调用处的位置信息作为显式参数传入日志函数。

具体实现步骤

1. 定义带元参数的日志函数

先写一个接收文件、行号等上下文信息的日志函数,同时处理OSLog和文件写入逻辑:

func log(message: String, file: String, line: Int, column: Int) {
    // 输出到OSLog
    let fileName = URL(fileURLWithPath: file).lastPathComponent
    os_log("%{public}@ %@:%d", log: .default, type: .default, message, fileName, line)
    
    // 写入日志文件的逻辑(示例)
    let logString = "\(Date()): \(message) | \(fileName):\(line)\n"
    if let fileHandle = try? FileHandle(forWritingTo: logFileURL) {
        fileHandle.seekToEndOfFile()
        fileHandle.write(logString.data(using: .utf8)!)
        fileHandle.closeFile()
    }
}

2. 实现Swift表达式宏

创建一个表达式宏,在展开时自动注入调用处的#file、#line、#column:

@freestanding(expression)
public macro Log(_ message: String) -> Void = #externalMacro(module: "YourMacroPackage", type: "LogMacro")

然后在宏实现模块里编写展开逻辑:

public struct LogMacro: ExpressionMacro {
    public static func expansion(
        of node: some FreestandingMacroExpansionSyntax,
        in context: some MacroExpansionContext
    ) throws -> ExprSyntax {
        guard let messageExpr = node.arguments.first?.expression else {
            throw MacroError.missingMessageArgument
        }
        // 直接拼接调用处的元数据参数
        return """
        log(message: \(messageExpr), file: #file, line: #line, column: #column)
        """
    }
}

enum MacroError: Error {
    case missingMessageArgument
}

3. 调用宏使用日志

在业务代码里直接调用宏即可,此时日志会自动带上调用处的文件和行号:

Log("用户完成支付")

宏展开后会变成:

log(message: "用户完成支付", file: "/Projects/App/PaymentViewController.swift", line: 89, column: 5)

关键注意事项

  • 不能依赖日志函数的默认参数(默认参数会使用函数定义处的上下文),必须通过宏显式传递调用处的#file、#line。
  • 宏需要放在单独的Swift Package模块中,按照Xcode的宏配置规范设置(在Package.swift中声明macro类型的target)。
  • Xcode 15及以上版本支持完整的Swift宏功能,确保开发环境版本符合要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 22:22:09