Logging Method signature using swift
I am trying to rewrite my logging class and I would like to know how to substitute PRETTY_FUNCTION or NSStringFromSelector(_cmd) in a swift file in order to track the method calls?
Special literals in swift are as follows (from [the swift guide]
#file
String The name of the file in which it appears.
#line
Int The line number on which it appears.
#column
Int The column number in which it begins.
#function
String The name of the declaration in which it appears.
Prior to Swift 2.2b4, these were
(https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html)):
__FILE__
String The name of the file in which it appears.
__LINE__
Int The line number on which it appears.
__COLUMN__
Int The column number in which it begins.
__FUNCTION__
String The name of the declaration in which it appears.
You can use these in logging statements like so:
println("error occurred on line \(__LINE__) in function \(__FUNCTION__)")
Check out a new library I've just published: https://github.com/DaveWoodCom/XCGLogger
It's a debug logging library for Swift.
The key to being able to use the #function
macros, is to set them as default values to your logging function. The compiler will then fill them in using the expected values.
func log(logMessage: String, functionName: String = #function) {
print("\(functionName): \(logMessage)")
}
Then just call:
log("my message")
And it works as expected giving you something like:
whateverFunction(): my message
More info on how this works: https://www.cerebralgardens.com/blog/entry/2014/06/09/the-first-essential-swift-3rd-party-library-to-include-in-your-project
I'd use something like this:
func Log(message: String = "", _ path: String = __FILE__, _ function: String = __FUNCTION__) {
let file = path.componentsSeparatedByString("/").last!.componentsSeparatedByString(".").first! // Sorry
NSLog("\(file).\(function): \(message)")
}
Improvements compared to previous answers:
- Uses NSLog, not print/println
- Does not use lastPathComponent which is not available on Strings anymore
- The log message is optional
Try this:
class Log {
class func msg(message: String,
functionName: String = __FUNCTION__, fileNameWithPath: String = __FILE__, lineNumber: Int = __LINE__ ) {
// In the default arguments to this function:
// 1) If I use a String type, the macros (e.g., __LINE__) don't expand at run time.
// "\(__FUNCTION__)\(__FILE__)\(__LINE__)"
// 2) A tuple type, like,
// typealias SMLogFuncDetails = (String, String, Int)
// SMLogFuncDetails = (__FUNCTION__, __FILE__, __LINE__)
// doesn't work either.
// 3) This String = __FUNCTION__ + __FILE__
// also doesn't work.
var fileNameWithoutPath = fileNameWithPath.lastPathComponent
#if DEBUG
let output = "\(NSDate()): \(message) [\(functionName) in \(fileNameWithoutPath), line \(lineNumber)]"
println(output)
#endif
}
}
Log using:
let x = 100
Log.msg("My output message \(x)")