Swift: 格式化控制台日志

Swift: format console-log

是否可以创建自定义日志功能?

这是默认的 println("hello world") 的样子:

2015-03-04 18:33:55.788 MyApp[12345:671253923] Hello World 

我想输出如下内容:

18:33 MyClass > myFunc [line 1] Hello World 

你应该对 NSObject 做一个扩展,像这样:

class MyClass: NSObject
{
    func myFunc()
    {
        myPrint("Hello World")
    }

}

extension NSObject
{
    func myPrint(text: String)
    {
        let timeFormatter = NSDateFormatter()
        timeFormatter.dateStyle = NSDateFormatterStyle.NoStyle
        timeFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
        let time = timeFormatter.stringFromDate(NSDate())

        let className = NSStringFromClass(self.classForCoder).pathExtension
        let function = __FUNCTION__

        let line = "\(__LINE__)"

        let result = time + " " + className + " > " + function + " " + line + " " + text
        println(result)
    }
}

let myClass = MyClass()

myClass.myFunc()

首先,对于时间,你可以得到当前的小时和分钟作为String:

func printTime()->String{
        let date = NSDate()
        let calendar = NSCalendar.currentCalendar()
        let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute, fromDate: date)
        let hour = components.hour
        let minutes = components.minute

        return "\(hour):\(minutes)"
}

对于函数等,您可以使用 Swift Literal Expressions __FILE____FUNCTION____LINE__

但你不想每次登录都设置它。所以你可以这样做:

func prettyPrint(print: String, file:String = __FILE__, functionName: String = __FUNCTION__, line:Int = __LINE__) {
    println("\(printTime()) \(file) > \(functionName) [line \(line)] \(print)")

}

你这样称呼prettyPrint:

prettyPrint("hey")

你将得到以下输出:

/Path/To/Your/File/MyClass.swift > hello [line 81] hey

但是因为您只想要 class 的名称,您可以使用以下函数删除路径:

func getFile(path:String = __FILE__)->String{
    var parts =  path.componentsSeparatedByString("/")
    return parts[parts.count-1]
}

或者,如 ChikabuZ 在他的回答中提到的,您可以直接检查 class:

let className = NSStringFromClass(self.classForCoder).pathExtension

最终函数

这里是最终函数:

func getFile(path:String = __FILE__)->String{
    var parts =  path.componentsSeparatedByString("/")
    return parts[parts.count-1]
}
func prettyPrint(print: String, functionName: String = __FUNCTION__, line:Int = __LINE__) {
    println("\(printTime()) \(getFile()) > \(functionName) [line \(line)] \(print)")

}

func printTime()->String{
    let date = NSDate()
    let calendar = NSCalendar.currentCalendar()
    let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute, fromDate: date)
    let hour = components.hour
    let minutes = components.minute

    return "\(hour):\(minutes)"
}

结果将是:

MyClass.swift > hello [line 81] hey

您还应该注意@emaloney 对这个问题的回答。具体来说

println()-based solutions result in output being captured by the Apple System Log (ASL).

最好切换到 NSLog 或一个成熟的日志系统

不幸的是,none 基于 println() 的解决方案导致输出被 Apple 系统日志 (ASL) 捕获。

ASL 是由 Mac OS 和 iOS 提供的日志工具,由 NSLog() 使用(在 Mac 上可见通过控制台应用程序)。因为 NSLog() 使用 ASL,所以 NSLog() 记录的日志条目将通过设备控制台可见。通过 println() 记录的消息将不会在 ASL 中捕获,因此,在发生某些事情后,没有机会返回控制台进行诊断。

NSLog() 有两大缺点:(1) 您无法自定义输出格式,以及 (2) 它在调用线程上做了很多工作,因此可能产生负面影响性能。

CleanroomLogger is a new Swift-based open-source API for logging。如果您熟悉 log4j 或 CocoaLumberjack,那么您就会了解 CleanroomLogger。

您可以通过提供您自己的 LogFormatter 实现来自定义您自己的输出格式,以确保您的日志消息的格式完全符合您的需要。

有关 CleanroomLogger 的更多信息,请访问 the GitHub project page