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。
是否可以创建自定义日志功能?
这是默认的 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。