在 Swift 中,编译器为我们准备了几个很有用的编译符号,用来处理类似这样的需求,它们分别是:
符号 | 类型 | 描述 |
---|---|---|
#file | string | 包含这个符号的文件的路径 |
#line | Int | 符号出现处的行号 |
#column | Int | 符号出现处的列 |
#function | String | 包含这个符号的方法名字 |
因此,我们可以通过使用这些符号来写一个好一些的 Log 输出方法:
func printLog<T>(message: T,
file: String = #file,
method: String = #function,
line: Int = #line)
{
print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
}
这样,在进行 log 的时候我们只需要使用这个方法就能完成文件名,行号以及方法名的输出了。最棒的是,我们不再需要对这样的输出进行维护,无论在哪里它都能正确地输出各个参数:
// Test.swiftfunc
method()
{
printLog("这是一条输出")
}
// 输出:Test.swift[62], method(): 这是一条输出
另外,对于 log 输出更多地其实是用在程序开发和调试的过程中的,过多的输出有可能对运行的性能造成影响。在 Release 版本中关闭掉向控制台的输出也是软件开发中一种常见的做法。如果我们在开发中就注意使用了统一的 log 输出的话,这就变得非常简单了。使用条件编译的方法,我们可以添加条件,并设置合适的编译配置,使 printLog的内容在 Release 时被去掉,从而成为一个空方法:
func printLog<T>(message: T,
file: String = #file,
method: String = #function,
line: Int = #line)
{ #if DEBUG
print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
#endif
}
新版本的 LLVM 编译器在遇到这个空方法时,甚至会直接将这个方法整个去掉,完全不去调用它,从而实现零成本。