I'm writing a LogUtil class, which simply pass arguments to 'print' functions with extra information like "filename, line NO. " etc. see below codes.
However, usually when we use 'print' function to output like this:
print("param1", "param2")
it outputs:
param1 param2
however, use my LogUtil to log,
LogUtil.d("tag", "param1", "param2"),
it outputs:
D - /LogUtil.swift(44): [["tag", "param1", "param2"]]
I want to output the original 'print' style:
D -/LogUtil.swift(44): tag param1 param2
how to fix this?Thanks!
class func p(level: LogLevel, items: Any...) {
//todo eric thread id
//todo eric fileName is too long
//todo eric loglevel control
//todo eric outputs to file
let filePath = __FILE__
let lineNo = __LINE__
print("\(getLogLevelDesc(level)) - \(filePath)(\(lineNo)):", items)
}
class func d(items: Any...) {
return p(LogLevel.DEBUG, items: items)
}
class func i(items: Any...) {
return p(LogLevel.INFO, items: items)
}
class func w(items: Any...) {
return p(LogLevel.WARN, items: items)
}
class func e(items: Any...) {
return p(LogLevel.ERROR, items: items)
}
class func fatal(items: Any...) {
return p(LogLevel.FATAL, items: items)
}
Variadic functions are functions (e.g. printf) which take a variable number of arguments.
A variadic parameter accepts zero or more values of a specified type. You use a variadic parameter to specify that the parameter can be passed a varying number of input values when the function is called.
A variadic function allows you to accept any arbitrary number of arguments in a function.
First you call LogUtil.d("tag", "param1", "param2")
. Since the items
parameter is declared as variadic Any...
, the local variable items
inside d
has type [Any]
, and has the value ["tag", "param1", "param2"]
.
Then d
calls p
, passing its own items
as the first argument for p
's items
parameter. Since p
's items
parameter is also variadic, d
could pass more arguments for p
's items
. That is, d
could call p(LogLevel.DEBUG, items: items, "more", "words")
. It doesn't, but it could.
Since p
's items
parameter is variadic Any...
, the local variable items
inside p
is also of type [Any]
, and its value is [["tag", "param1", "param2"]]
. It is an array of three elements inside an array of one element.
What you need to do is make p
, or some new function, take a non-variadic items
parameter, and call that from d
and all your other variadic functions.
Also, __FILE__
and __LINE___
are deprecated. If you've upgraded to Xcode 7.3, you should use the new #file
and #line
special forms instead.
But you still have a problem: #file
and #line
will return the file and line where they are used inside function p
. That's probably not what you want. You probably want the file and line where the program calls d
or i
or whatever.
To do that, you pass the file and line arguments to d
(and the other functions), with default values of #file
and #line
. The defaults will be expanded at the call site, so you'll get the file and line number of the call to d
or i
or whatever.
So ultimately you want one function that knows how to take an [Any]
(with only one level of array wrapping) and turn it into a space-separated string. Here's how you do that:
struct LogUtil {
enum LogLevel: String {
case Debug
case Info
case Warning
case Error
case Fatal
}
// The low-level function that all the others call.
private static func log(level level: LogLevel, file: String, line: Int, items: [Any]) {
let itemString = items.map { String($0) }.joinWithSeparator(" ")
print("\(level) - \(file)(\(line)): \(itemString)")
}
Note that log(level:file:line:items:)
is not variadic, so it won't add another array wrapper around its items
.
Then you define all your user-visible functions to call the log
function:
static func p(level: LogLevel, items: Any..., file: String = #file, line: Int = #line) {
log(level: level, file: file, line: line, items: items)
}
static func d(items: Any..., file: String = #file, line: Int = #line) {
log(level: .Debug, file: file, line: line, items: items)
}
static func i(items: Any..., file: String = #file, line: Int = #line) {
log(level: .Info, file: file, line: line, items: items)
}
// other level-specific functions here...
}
When you call LogUtil.d("tag", "foo", "bar")
, the output looks like you want:
Debug - /var/folders/kn/<snip>/playground282.swift(33): tag foo bar
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With