考虑 OSLog
框架中的 Logger
类:Logger
由于OSLog API不允许查询诸如文件名、调用日志命令的行和函数等信息,我想将这些值“嵌入”到日志条目中本身。
这可以通过向Logger
添加新方法来轻松完成:
extension Logger {
func d_debug(_ message: @autoclosure () -> Any, _ file: String = #file, _ function: String = #function, line: Int = #line, context: Any? = nil) {
let converted = (file as NSString).lastPathComponent + ":" + String(line) + ":" + function + ": " + "\(message())"
debug("\(converted)")
}
}
这种方法的问题是我必须使用 d_debug
方法,而不是默认使用的标准 debug
方法。因此,这种修改后的方法会将实现细节“泄漏”到扩展之外。
我正在寻找的是一个利用方法重载并使用不同类型的选项,即 String
作为输入参数,这样我的方法将是首选,而不是原始的日志方法记录器
。
例如,原始签名如下所示:
///
/// - Warning: Do not explicity create OSLogMessage. Instead pass a string interpolation.
///
/// - Parameter message: A string interpolation.
public func debug(_ message: OSLogMessage)
但是,我想要一个这样的方法:
func debug(_ message: @autoclosure () -> String, _ file: String = #file, _ function: String = #function, line: Int = #line) {
并保持此方法甚至存在的概念对调用站点完全隐藏(如果可能)。
理想情况下,如果我删除扩展,代码仍然应该可以编译。
有什么选择可以实现这种行为吗?或者类似的事情会涉及运行时动态修补?
最佳答案
如果我理解正确,您可以将您的方法命名为 debug
,并使用 log(level:_:)
避免无限递归的方法。
log(level: .debug, "\(custom)")
Swift 将解析对您自己的方法而不是内置方法的 debug(...)
调用,as long as you are in the same module as the extension .
还可以考虑使用OSLogMessage
提供的自定义字符串插值。
func debug(_ message: @autoclosure () -> String, _ file: String = #file, _ function: String = #function, line: Int = #line) {
log(level: .debug, "\((file as NSString).lastPathComponent):\(line):\(function):\(message())")
}
无论哪种方式,调用者都无法使用 OSLogMessage 提供的自定义字符串插值,例如自定义格式、对齐方式和隐私。我认为没有办法实现这一点。
关于 swift 扩展: augment existing class with method overloading,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77093841/