0

In Objective C, I have defined various levels of logging by putting this in .pch file:

 #ifdef MY_DEBUG  
 #define LOG_LEVEL    2
 #define MyLog(...)     { if(LOG_LEVEL <= 0) NSLog(__VA_ARGS__); }
 #define MyLog1(...)    { if(LOG_LEVEL <= 1) NSLog(__VA_ARGS__); }
 #define MyLog2(...)    { if(LOG_LEVEL <= 2) NSLog(__VA_ARGS__); }
 #define MyLog3(...)    { if(LOG_LEVEL <= 3) NSLog(__VA_ARGS__); }
 #define MyLog4(...)    { if(LOG_LEVEL <= 4) NSLog(__VA_ARGS__); }

 #else
 #define MyLog(...)
 #define MyLog1(...)
 #define MyLog2(...)
 #define MyLog3(...)
 #define MyLog4(...)
 #endif

How do I achieve same thing in Swift? Also in Xcode 10.3, I tried defining MY_DEBUG in preprocessor macros for DEBUG version, but it has no effect in my Swift project. What could be wrong?

1

1 Answer 1

1

You might try something like this:

public let kMyLogLevel = 2

#if DEBUG
public func MyLog(text: String)  { if kMyLogLevel <= 0 { NSLog(text) } }
public func MyLog1(text: String) { if kMyLogLevel <= 1 { NSLog(text) } }
public func MyLog2(text: String) { if kMyLogLevel <= 2 { NSLog(text) } }
public func MyLog3(text: String) { if kMyLogLevel <= 3 { NSLog(text) } }
public func MyLog4(text: String) { if kMyLogLevel <= 4 { NSLog(text) } }
public func MyLog5(text: String) { if kMyLogLevel <= 5 { NSLog(text) } }
#else
public func MyLog(text: String)  { }
public func MyLog1(text: String) { }
public func MyLog2(text: String) { }
public func MyLog3(text: String) { }
public func MyLog4(text: String) { }
public func MyLog5(text: String) { }
#endif

This can be put in any module at file scope (i.e., not inside a class or other type.)

Note that the input is not a variable argument list, rather a simple text string. The Swift way is to use String interpolation, like so:

MyLog("The value is: \(value)")

Also, Swift doesn't support preprocessor macros in the same way you're used to with Objective-C. In Swift, you can only provide conditional compilation flags and you can only test for existence of those flags (they cannot be assigned a value.) In addition, you cannot create these flags in code (there is no #define). These flags must be sent into the compiler's command line (ex: -DDEBUG). See the top answer to this question for more information.

Swift doesn't provide a DEBUG flag by default, you'll need to set that in the build options for your project/target. See the question linked to above for details on this.

The DEBUG flag works fine for conditional compilation, but not for your log level. For this, common practice is to use a constant (via the let keyword.)

Sign up to request clarification or add additional context in comments.

5 Comments

Ok thanks. How do I define my own debug flag in preprocessor macros in XCode. I defined MY_DEBUG for the Debug version but it has no effect.
How/where did you define MY_DEBUG? And how are you trying to use it?
There is one problem. I get a crash when I call - MyLog("-[%@ %@] called", NSStringFromClass(type(of: self)), #function)
How to handle #function in MyLog?
This solution doesn't directly support variable arguments ([%@ %@]). Use string interpolation (as explained in the answer) or use the String(format:) initializer to format the string before passing to MyLog.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.