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?

jscs
  • 63,694
  • 13
  • 151
  • 195
Deepak Sharma
  • 5,577
  • 7
  • 55
  • 131
  • 1
    Check out https://developer.apple.com/documentation/os/oslog , it has level of logging support out of the box. – Kamil.S Aug 08 '19 at 19:13

1 Answers1

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.)

pauln
  • 598
  • 6
  • 19
  • 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. – Deepak Sharma Aug 09 '19 at 07:13
  • How/where did you define `MY_DEBUG`? And how are you trying to use it? – pauln Aug 09 '19 at 15:48
  • There is one problem. I get a crash when I call - MyLog("-[%@ %@] called", NSStringFromClass(type(of: self)), #function) – Deepak Sharma Aug 20 '19 at 08:11
  • How to handle #function in MyLog? – Deepak Sharma Aug 20 '19 at 08:11
  • 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`. – pauln Aug 21 '19 at 11:50