Do I need to disable NSLog before release Application?
When releasing an app for iPhone, if I disable NSLog();
will it perform better?
Solution 1:
One way to do it is to go into your Build settings and under the Debug configuration add a value to "Preprocessor Macros" value like:
DEBUG_MODE=1
Make sure you only do this for the Debug configuration and not for Beta or Release versions. Then in a common header file you can do something like:
#ifdef DEBUG_MODE
#define DLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DLog( s, ... )
#endif
Now instead of NSLog
use DLog
everywhere. When testing and debugging, you'll get debug messages. When you're ready to release a beta or final release, all those DLog
lines automatically become empty and nothing gets emitted. This way there's no manual setting of variables or commenting of NSLogs
required. Picking your build target takes care of it.
Solution 2:
Update for Xcode 5 & iOS 7
note : for a Xcode 7 / Swift 2.1 solution to remove print() statements in a release build, find my answer here.
Yes, you should remove any NSLog statement in your release code, as it just slows down your code, and isn't of any use in a release version. Fortunately, in Xcode 5 (iOS 7), it is amazingly simple to remove all your NSLog statements 'automatically' in release builds. So why not do it.
First the 3 steps to take, then some explanation
1) in your Xcode project, locate the 'yourProjectName-prefix.pch' file (normally you'll find this under the group 'supporting files', where your main.m file is located
2) add these 3 lines at the end of the '.pch' file :
#ifndef DEBUG
#define NSLog(...);
#endif
3) test the difference between your 'debug' and 'release' version. One way to do this is through 'edit scheme' -> 'run app name' -> under the tab 'info' select using the drop-down box between debug & release. In the release version you won't see any NSLog output in the debug console !
How does this all work?
first of all, one must know that a preprocessor is relatively 'dumb', and just acts as a 'text replacer' before the compiler is called. It replaces anything you '#define' by what follows the #define
statement.
#define NSLog(...);
The (...)
stands for 'anything' between the brackets (). Mind also the ;
at the end. This is not strictly necessary as the compiler will optimize this away, but I like to put it there, as it is more 'correct'. After our #define
there is 'nothing', so the preprocessor will replace it with 'nothing', and so it will just throw away the complete line, starting at NSLog...
until and including the ;
.
define statements can be made conditional using #ifdef
(if defined) or #ifndef
(if not defined)
here we write #ifndef DEBUG
, which means 'if the symbol DEBUG is not defined'. The #ifdef
or #ifndef
need to be 'closed' with #endif
Xcode 5 defines by default the 'DEBUG' symbol for us when de build mode is 'DEBUG'. In 'release' this is not defined. you can verify this under your project settings, tab 'Build settings' -> scroll down to the section 'Apple LLVM 5.0 - Preprocessing' -> preprocessor macros. You'll see that the symbol 'DEBUG' is not defined for release builds !
finally, the .pch file is created by Xcode automatically, and automatically included in every source file during the compilation time. So it is as if you would have put the whole #define
thing into each of your source files.
Solution 3:
Almost all above answers sugest a solution but not explain the problem. I did a search in google, and found the reason. Here is my answer:
Yes, if you comment out NSLog in your release version, the performance will become better. Because NSLog is pretty slow. Why? NSLog will do two things 1) write log messages to Apple System Logging(ASL), 2) if the app runs in xcode it write to stderr too.
The main problem lays in the first one. In order to achieve thread safe, every time NSLog is called, it opens an connection to ASL facility, sends message, and closes the connection. The connection operation is very expensive. Another reason is that NSLog spends some time to get the timestamp to log.
Reference from here.
Solution 4:
My personal favourite is to use a variadic macro.
#ifdef NDEBUG
#define NSLog(...) /* suppress NSLog when in release mode */
#endif
Solution 5:
In addition to all the people who wisely commented that not calling NSLog()
at all in production runs slightly faster, I'll add that:
All those NSLog()
output strings are visible to anyone who downloads your app from the store and runs it with the device plugged into a mac running Xcode (through the Organizer window).
Depending on what information you log (and especially if your app contacts a server, does authentication, etc.), this can be a serious security issue.