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
}