topgun
topgun

Reputation: 2573

Setting a flag in compiler for NSLog not to show

Is there any particular flag which can be set to not display NSLog output in either debug or release?

Thanks.

Upvotes: 2

Views: 1014

Answers (7)

Cœur
Cœur

Reputation: 38667

Default flag with a new Xcode project is DEBUG for Debug and none for Release. So you will hide NSLog in Release this way:

#ifndef DEBUG
#   define NSLog(...)
#   define NSLogv(...)
#endif

Or if you want pretty custom logs as well (not using #ifdef here because no simple #elifdef):

#if DEBUG
#   define NSLog(format, ...) NSLog((@"%s " format), __PRETTY_FUNCTION__, ##__VA_ARGS__)
#   define NSLogv(format, ...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [[NSString alloc] initWithFormat:format arguments:__VA_ARGS__])
#elif ADHOC
    // default logs
#else// Release
#   define NSLog(...)
#   define NSLogv(...)
#endif

And if you want to override those macros and still log something sometimes, you can use:

(NSLog)(@"This log is always visible!");

Now, how to hide those as well? It would require you to #define NSLog NoLog and define NoLog as an extern function with an empty implementation like void NoLog(NSString *format, ...) {}. But it could be cleaner to avoid using (NSLog) altogether and instead use a function with a LogLevel enum:

typedef NS_ENUM(NSUInteger, LogLevel) {
    LogLevelRelease,
    LogLevelAdHoc,
    LogLevelDeveloper,
};

void CustomLog(LogLevel level, NSString *format, ...) {
#if !DEBUG
    if (LogLevel == LogLevelDeveloper)
        return;
#if !ADHOC
    if (LogLevel == LogLevelAdHoc)
        return;
#endif
#endif
    va_list ap;
    va_start (ap, format);
    NSLogv(format, ap);
    va_end (ap);
}

The drawback of this CustomLog is that arguments get always evaluated, even in Release. So an optimal solution is multiple macros:

#define NSLog(format, ...) NSLog((@"%s " format), __PRETTY_FUNCTION__, ##__VA_ARGS__)
#if DEBUG
#   define DebugLog(...) NSLog(__VA_ARGS__)
#   define AdHocLog(...) NSLog(__VA_ARGS__)
#   define ReleaseLog(...) NSLog(__VA_ARGS__)
#elif ADHOC
#   define DebugLog(...)
#   define AdHocLog(...) NSLog(__VA_ARGS__)
#   define ReleaseLog(...) NSLog(__VA_ARGS__)
#else// Release
#   define NSLogv(...)
#   define DebugLog(...)
#   define AdHocLog(...)
#   define ReleaseLog(...) NSLog(__VA_ARGS__)
#endif

Upvotes: 1

jpswain
jpswain

Reputation: 14732

Adding this b/c none of the answers seem to address warnings you may have (depending on project settings) with some of these approaches.

This is the only way I could find to suppress NSLog without getting any warnings. Otherwise I get a ton with the settings we use (warn on unused variables).

#undef NSLog

#define NSLog(fmt, ...) if (0) { printf("%s", [[NSString stringWithFormat:fmt, ##__VA_ARGS__] UTF8String]); }

Then all you need to do is put that in whatever pch file you use for your release builds or wherever you want to suppress the logs.

Credit to @Hot Licks for the example of how to make the variable "used".

Upvotes: 0

WDUK
WDUK

Reputation: 19030

In Xcode, you can define macros for particular build configurations. For example, here I have DEBUG defined for Debug builds, and nothing for release builds.

DEBUG flag set for Debug Build Config in Xcode

Then to use this in the code, wrap your NSLog(...) statements in (or however you choose to use the macro, update:darren's method is quite good with this technique):

#ifdef DEBUG
    NSLog(...);
#endif

Use the same mechanism for release configuration only logic.

You can use this ability if you have various number of build configurations, and you can define more than one macro if you want to enable/disable different levels of functionality for different build configurations.

Upvotes: 2

Hot Licks
Hot Licks

Reputation: 47699

Generally, people write their own macro -- something like DebugLog -- for logs to be "compiled out":

#undef DebugLog
#ifdef DEBUG_MODE
#define DebugLog( s, ... ) NSLog( @"%@", [NSString stringWithFormat:(s), ##__VA_ARGS] )
#else
#define DebugLog( s, ... )
#endif

Upvotes: 2

D.C.
D.C.

Reputation: 15588

One option might be to use a macro as a replacement for NSLog (if its easy for you to change things at this point). I like the prefix header file these guys use:

http://www.cimgf.com/2010/05/02/my-current-prefix-pch-file/

Basically their logging function is:

#ifdef DEBUG
  #define DLog(...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#else
  #define DLog(...) do { } while (0)
#endif

So if you are not in a DEBUG build, the logging macro becomes a no-op.

Upvotes: 2

Felix
Felix

Reputation: 35384

You can define a macro in the precompiled header (.pch) to disable NSLog:

#ifdef RELEASE
#   define NSLog(...)
#endif

This disables NSLog in release builds.

Upvotes: 0

Evol Gate
Evol Gate

Reputation: 2257

check for Debug mode using this macro

#ifdef DEBUG
//NSLog(@"XYZ");
#endif

Above NSLog will not get printed in Release mode

Upvotes: 0

Related Questions