You could take a similar approach as the built-in assert()
function, which is
explained in the Swift blog:
The logTrace
function takes an "auto-closure" as the first argument:
func logTrace(message: @autoclosure () -> String, file: StaticString = __FILE__, line: UWord = __LINE__) {
#if DEBUG
let msg = message()
println("\(file):\(line): \(msg)")
#endif
}
Example usage:
let height = 13
logTrace ( "height = \(height)" )
// Output: /Users/.../main.swift:14: height = 13
To make this work you have to add "-DDEBUG" to the "Other Swift Flags" for the
debug configuration, compare

The advantage of this method is that (as with assert()
) the block is not
evaluated at all in the Release configuration, where "DEBUG" is not defined, e.g. in
logTrace ( someFunctionReturningAString() )
the function would not be called in the Release configuration, so any side-effects
or performance overhead is avoided.
Update for Swift 2:
func logTrace(@autoclosure message: () -> String, file: String = __FILE__, line: Int = __LINE__) {
#if DEBUG
let msg = message()
print("\(file):\(line): \(msg)")
#endif
}
Update for Swift 3:
func logTrace(_ message: @autoclosure () -> String, file: String = #file, line: Int = #line) {
#if DEBUG
let msg = message()
print("\(file):\(line): \(msg)")
#endif
}