0

I have a special logging function, let's call it JLog() which I have written to keep track of logging data, but only when testing in the simulator and on my test device. I set a DEBUG preprocessor flag in my Xcode project, set only for the development mode, not in production. JLog() uses this to know whether to output the log message. It looks sort of like this:

void JLog(NSString *message) {
#ifdef DEBUG
    NSLog(@"%@", message);
#endif
}

I use this instead of wrapping all of my NSLog() calls with #ifdef DEBUG - it makes my code easier to read and less prone to bugs.

The problem is that even though the app doesn't print the log messages in production, it still needs to construct the messages which are passed to JLog() - which are sometimes expensive and often uses a lot of memory. For example, if I have code like this:

NSError *error = <something>;
JLog([NSString stringWithFormat:@"Error: %@", error);

... then the app is forced to allocate an NSString, insert the NSString-ified version of error into it, and pass it to JLog() - only to do nothing with it. This seems very wasteful to me.

What I'd like to do is, somehow, instruct Xcode to simply not compile the JLog() code in production. That way, code such as the above example of constructing an error message which won't end up being printed to the log anyway, won't need to be called at all. How can I do this?

Jason
  • 14,517
  • 25
  • 92
  • 153
  • A good way: http://stackoverflow.com/questions/969130/how-to-print-out-the-method-name-and-line-number-and-conditionally-disable-nslog I've various DLog-kind of function (DLogJSON, DLogDB (for DataBase check), etc. All that put in xxx-Prefix.pch – Larme Dec 02 '13 at 13:55
  • You don't need to explicitly define DEBUG, Xcode does this automatically fro debug builds. – Abizern Dec 02 '13 at 14:48

2 Answers2

3

Replace your

void JLog(NSString *message) {
#ifdef DEBUG
    NSLog(@"%@", message);
#endif
}

with

#ifdef DEBUG
void JLog(NSString *message) {
    NSLog(@"%@", message);
}
#else
#define JLog(args) {}
#endif
Cyrille
  • 25,014
  • 12
  • 67
  • 90
  • OK - but then won't the `JLog()` code within my app still compile? It just won't have anything to do when it runs. – Jason Dec 02 '13 at 14:29
  • 1
    Before compilation, the preprocessor will replace any call to `JLog(whatever)` into `{}`. Then any method call in `whatever` won't even be seen by the compiler. – Cyrille Dec 02 '13 at 15:02
  • Right - but if I do `JLog([NSString stringWithFormat:@"Error: %@", error)` will it still execute the code inside of the parentheses, creating the NSString? – Jason Dec 02 '13 at 16:12
  • No. It won't execute anything as the preprocessor did replace the whole `JLog(...)` line with `{}` even before the program got compiled. – Cyrille Dec 02 '13 at 17:26
  • The key is to understand that the preprocessor does its job BEFORE the compile phase, as its name suggests. – Cyrille Dec 02 '13 at 17:27
0

The following will only output your log messages when DEBUG is set.

#ifdef DEBUG
#define JLog(...) NSLog(__VA_ARGS__)
#else
#define JLog(...)
#endif

And you use it as you use NSLog

JLog(@"Some log message with some parameters %@ and integer %d", @"String param", 7);
Eric Genet
  • 1,260
  • 1
  • 9
  • 19