I was told this a few times in this very site, but I wanted to make sure this is really the case.
I was expecting to be able to sprinkle NSLog function calls throughout my code, and that Xcode/gcc would automatically strip those calls out when building my Release/Distribution builds.
Should I avoid using this? If so, what alternatives are most common between experienced Objective-C programmers?
NSLog calls can be left in production code, but should only be there for truly exceptional cases, or information that it is desired that will be logged to the system log.
Applications which litter the system log are annoying, and come across as unprofessional.
I agree with Matthew. There's nothing wrong with NSLog in production code. In fact, it can be useful to the user. That said, if the only reason you're using NSLog is to help debug, then, yes, that should be removed before you release.
Furthermore, since you've tagged this as an iPhone question, NSLog takes resources, which is something the iPhone has precious little of. If you're NSLogging anything on the iPhone, that takes away processor time from your app. Use it wisely.
You shouldn't be needlessly verbose with printf or NSLog in release code. Try only doing a printf or NSLog if the app has something bad happen to it, I.E. an unrecoverable error.
As noted in other answers you can use a #define to alter whether NSLog is used or not at compile time.
However a more flexible way is to use a logging library like Cocoa Lumberjack thatallows you to change whether something is logged at runtime as well.
In your code replace NSLog by DDLogVerbose or DDLogError etc, add a #import for the macro definitions etc and setup the loggers, often in the applicationDidFinishLaunching method.
To have the same effect as NSLog the configuration code is
Preprocessor macros are indeed great for debugging. There's nothing wrong with NSLog(), but it's simple to define your own logging function with better functionality. Here's the one I use, it includes the file name and line number to make it easier to track down log statements.
I found it easier to put this entire statement in the prefix header rather than its own file. You could, if you wanted, build a more complicated logging system by having DebugLog interact with normal Objective-C objects. For instance, you could have a logging class that writes to its own log file (or database), and includes a 'priority' argument you could set at runtime, so debug messages are not shown in your release version, but error messages are (if you did this you could make DebugLog(), WarningLog(), and so on).
Oh, and keep in mind
#define DEBUG_MODE
can be re-used in different places in your application. For example, in my application I use it to disable license key checks and only allow the application to run if it's before a certain date. This lets me distribute a time limited, fully functional beta copy with minimal effort on my part.EDIT: The method posted by Marc Charbonneau, and brought to my attention by sho, is far better than this one.
I have deleted the portion of my answer which suggested using an empty function to disable logging when debug mode is disabled. The portion that deals with setting an automatic preprocessor macro is still relevant, so it remains. I have also edited the name of the preprocessor macro so that it fits better with Marc Charbonneau's answer.
To achieve the automatic (and expected) behaviour in Xcode:
In the project settings, go to the "Build" tab, and select the "Debug" configuration. Find the "Preprocessor Macros" section, and add a macro named
DEBUG_MODE
....
EDIT: See Marc Charbonneau's answer for the proper way to enable and disable logging with the
DEBUG_MODE
macro.