4

Update:

More info on this here:

Is it true that one should not use NSLog() on production code?

~~~~~~~~~~~~~~~~~~~~~~~~

Situation

I have some pretty beafy NSLog calls that I use for debugging the more complex parts of my application. However, I just recently learned that these affect runtime performance!

Goal

I would like to remove my NSLog calls during any run where I am not actually performing Product > Run (aka command-R) from within Xcode - ESPECIALLY in situations when this thing is deployed on the App Store, but also when I am running the app when disconnected from Xcode (i.e. just tapping the icon while walking down the street).

Proposed Solution?

Assuming I've created a Preprocessor Macro of VIEW_DEBUG, would the following implementation effectively remove NSLog calls from executing in the cases I've described above?

    <bunch of code>

#ifdef VIEW_DEBUG
    NSLog(@"really complex logs entries");
#endif

    <even more code>

This is a difficult one for me to 'test', so I figured I would appeal to more experienced minds. :)

Xcode Settings (for reference)

xcode settings

Community
  • 1
  • 1
toblerpwn
  • 5,415
  • 8
  • 38
  • 46

2 Answers2

12

A common solution is to place the following code in your Prefix file (or you may create a dedicated class and #include it as needed):

#ifdef DEBUG    
#define DebugLog(...) NSLog(__VA_ARGS__)
#else
#define DebugLog(...) while(0)
#endif

Xcode already defines DEBUG for you when performing a debug build (as shown in your screenshot). VA_ARGS is a way of creating variadic macros that was introduced in C99. the do/while ensures that DebugLog has the same net syntactic effect even when it doesn't do anything — don't worry about the pointless loop, the optimiser will remove it for you.

Then you can just use DebugLog exactly as you'd use NSLog. This will do exactly what you propose with VIEW_DEBUG but without you having to copy and paste the #ifdef condition a thousand times over.

toblerpwn
  • 5,415
  • 8
  • 38
  • 46
Tommy
  • 99,986
  • 12
  • 185
  • 204
  • #define DebugLog(...) NSLog(__VA_ARGS__) also works. Also, you don't need the do {} while(0) with GCC or LLVM, #define DebugLog(...) works fine. – MrAnonymous Aug 26 '12 at 23:58
  • Fixed markup, I take no credit for this: `#define DebugLog(...) NSLog(__VA_ARGS__)` –  Aug 27 '12 at 00:05
  • Thanks to both commenters (though I'm not permitted to @ both) — that's what I get for blindly copying and pasting from a project I had open with quite a history. Corrections taken on board, and I've marked it as community wiki since it now wouldn't be very accurate to claim ownership of the answer. – Tommy Aug 27 '12 at 01:14
  • @Tommy & crew - New to macros, so just to confirm I understand: these `#define` calls are creating a new macro named `DebugLog(...)` (but it could have been named anything, right?) and the `...` represents my input. So if I code `DebugLog(@"test!")`, in DEBUG mode it will swap out `NSLog(@"test!")`, and in non-DEBUG mode it will swap out `while(0)` for all of my `NSLog`s - correct? (Or, per MrAnonymous, do I even need the `while(0)`?) -- Also, will DEBUG be 'on' when my phone is disconnected from Xcode but I am running a 'Development' build? – toblerpwn Aug 27 '12 at 16:37
  • @toblerpwn that's pretty much it — you'll get DebugLog (or whatever you want to call it) that acts exactly like you'd typed `NSLog` when DEBUG is defined but like you'd typed `while(0)` or nothing at all otherwise. It'll depend only on the type of build, not on whether your device is tethered, but will prevent you from releasing with logs and you can't make accurate assessments of release performance from development builds anyway — that's why when you profile with Instruments it automatically does a release build, for example. – Tommy Aug 27 '12 at 16:51
3

I always use DLog in my code, it works great.

// DLog is almost a drop-in replacement for NSLog
// DLog();
// DLog(@"here");
// DLog(@"value: %d", x);
// Unfortunately this doesn't work DLog(aStringVariable); you have to do this instead DLog(@"%@", aStringVariable);
#ifdef DEBUG
#   define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#   define DLog(...)
#endif

// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

More info: The Evolution of a Replacement for NSLog

fannheyward
  • 18,599
  • 12
  • 71
  • 109