Detect if the iPhone is running a Debug/Distribution build at runtime - iphone

Is it possible at runtime to detect if the application that is running was compiled with debug or distribution.

In the Project Info, for a Debug configuration, add a Preprocessor Macro of "DEBUG" (in the GCC 4.2 - Preprocessing section).
In your code you can use #ifdef to see if DEBUG is defined if you want some code included or not for debug builds. Or you can even set a variable (I can't imagine why you would want this):
#ifdef DEBUG
BOOL isBuiltDebug = YES;
#else
BOOL isBuiltDebug = NO;
#endif
EDIT: Well, another way is to define a boolean value in a Preprocessor Macro, ie: "DEBUG_BUILD=1" for the Debug configuration, and "DEBUG_BUILD=0" for the Release configuration. Then you can use that value in your code:
if (DEBUG_BUILD) {
....
}
Just be careful not to use a macro name that could match a name that is already in your code or in any .h file that you might include either, because the preprocessor will replace it and it's a real pain to find those kinds of bugs.

Without having to think about defining a custom preprocessor macro, you can just write a custom method like this one :
+ (BOOL) isInDebugMode
{
#ifndef __OPTIMIZE__ // Debug Mode
return YES;
#else
return NO;
#endif
}
Or just write your code inline within those statements :
#ifndef __OPTIMIZE__ // Debug Mode
// Your debug mode code
#else
// Your release mode code
#endif
The __OPTIMIZE__ preprocessor setting in automatically set by the compiler regarding your project settings, so you don't have to worry about it.

Related

XCode environment variables vs property list for TEST and PROD

I am somewhat noobish to IOS development and wanted to find the best way to manage my environment variables depending on the build scheme of my app.
So if I perform a DEBUG build, I want my app to retrieve all data from server say
http://debugserver1.blah.com
And likewise, if I perform a TEST build, I want my app to retrieve all data from server say
http://testserver2.blah.com
And for prod
http://prodserver.blah.com
I am sure this is an uncommon scenario and am trying to figure out what is the BEST way to approach this. I've looked into Environment variables, but I don't think that makes sense, so I am leaning to pLists.
Can you guys assist in helping me associate certain pLists to certain scheme builds?
This is a very common scenario, and easily handled. By default, when you create a new project, DEBUG is #defined for the Debug build configuration, but not for the Release configuration. For your Test configuration, you'll probably copy Debug and add a #define for TEST
I'd probably go down the route of creating a manager class to handle your API calls, and add a property:
#property (nonatomic, strong) NSString * baseURLString;
Then in your class's init method:
#if defined(DEBUG)
self.baseURLString = "http://debugserver1.blah.com";
#elif defined(TEST)
self.baseURLString = "http://testserver1.blah.com";
#else
self.baseURLString = "http://prodserver1.blah.com";
#endif
Then use the baseURLString to construct URLs to make your API calls.
You can do this by using a definition file that is #included into each of your source files. For example:
servername.h
#define DEBUG_BUILD
//#define TEST_BUILD
//#define PRODUCTION_BUILD
#if defined(DEBUG_BUILD)
#define SERVER_NAME "http://debugserver1.blah.com"
#elif defined(TEST_BUILD)
#define SERVER_NAME "http://testserver2.blah.com"
#elif defined(PRODUCTION_BUILD)
#define SERVER_NAME "http://prodserver.blah.com"
#else
#error Must define build type
#endif
Then, in each of your source files where you need to use SERVER_NAME, at the top do:
#include "servername.h"
The above will work, but you would need to edit servername.h to change the build type. A better way is to remove the #define statements from servername.h, and use the build settings in Xcode to define the build type. To do this, go to your Build Settings and scroll down until you find the Preprocessing section. A default project looks like this:
In that section, for each type of build, you can add DEBUG_BUILD, TEST_BUILD, or PRODUCTION_BUILD as needed.

iPhone #ifdef directive not working as expected

I am using Xcode 4 to update one of my apps that were previously developed with Xcode 3.
On one part of the code I had:
#define CREATE YES
and later...
#ifdef CREATE
// do stuff
#endif
on Xcode 3, this branch would be executed just if CREATE was yes but now in Xcode 4 it is being executed all the time.
As far as I see that Xcode 4 approach appears to be the most correct, as I am asking if the variable is defined, Xcode 3 worked somehow as I wanted.
So, now, how do I test for the boolean value of CREATE on Xcode 4?
something like:
#ifdef CREATE == YES
// DO STUFF
#endif
thanks.
#define CREATE 1
#if CREATE
// do stuff
#else
//do other stuff
#endif
i think that's what you're looking for?
try using the #if directive instead of #ifdef
#define CREATE NO
#if CREATE
//This should not run.
#endif

What's the use of #ifdef and #endif processor directives in iPhone?

I want to know about the use of #ifdef, #ifndef and #endif and which case, have to used those conditionals and what's the use of it? Whats the difference between the #ifdef and #ifndef?
For eg:
#define MY_Global
#ifdef MY_Global
// write some code (Inside the method)
#endif
or,
#ifdef MY_Global
-(void) customMethod
{
// Do something
}
#endif
Which one is correct, whether it should write only inside method or it does works outside method?. I haven't used this one before. so please Explain me?
Thanks!
AFAIK, #ifdef = "if defined" and #ifndef = "if not defined". These conditionals are useful, for example if you want a certain code to be compiled only for the simulator, then you'd write something like:
#if TARGET_IPHONE_SIMULATOR
#import "AccelerometerSimulation.h"
#endif
Which means, when you compile for the simulator, the AccelerometerSimulation.h will be imported. If you are compiling on a device, it is ignored totally. Hope that helps.

Programmatically determine active configuration

Is there a way to determine the active configuration (that means Debug or Release) in code? Something along the lines of
#ifdef XCodeConfigurationDebug
...
#endif
#ifdef XCodeConfigurationRelease
...
#endif
I know that it's possible to do this by adding custom compiler flags. However, I'm looking for a more global solution.
There is the flag __OPTIMIZE__ that is defined when on RELEASE mode, and so:
#ifndef __OPTIMIZE__
// code for debug mode
#else
// code for release
#endif
i figure it out using the preprocessor declarations. you can add your own definition, or NDEBUG is another common one to declare in release.
You can also add your own preprocessor macros per configuration on your target's build settings. Ex.:
Debug
GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1
Release
GCC_PREPROCESSOR_DEFINITIONS = RELEASE=1
And then in your code
#ifdef DEBUG
...
#else
...
#endif

#if 0 as a define

I need a way to define a FLAGS_IF macro (or equivalent) such that
FLAGS_IF(expression)
<block_of_code>
FLAGS_ENDIF
when compiling in debug (e.g. with a specific compiler switch) compiles to
if (MyFunction(expression))
{
<block_of_code>
}
whereas in release does not result in any instruction, just as it was like this
#if 0
<block_of_code>
#endif
In my ignorance on the matter of C/C++ preprocessors I can't think of any naive way (since #define FLAGS_IF(x) #if 0 does not even compile) of doing this, can you help?
I need a solution that:
Does not get messed up if */ is present inside <block_of_code>
Is sure to generate 0 instructions in release even inside inline functions at any depth (I guess this excludes if (false){<block_of_code>} right?)
Is standard compliant if possible
Macros are pretty evil, but there's nothing more evil than obfuscating control statements and blocks with macros. There is no good reason to write code like this. Just make it:
#ifdef DEBUG
if (MyFunction(expression))
{
<block_of_code>
}
#endif
The following should do what you want:
#ifdef DEBUG
# define FLAGS_IF(x) if (MyFunction((x))) {
# define FLAGS_ENDIF }
#else
# define FLAGS_IF(x) if(0) {
# define FLAGS_ENDIF }
#endif
The if(0) should turn into no instructions, or at least it does so on most compilers.
Edit: Hasturkun commented that you don't really need the FLAGS_ENDIF, so you would instead write your code like this:
FLAGS_IF(expression) {
<block_of_code>
}
with the follow macros:
#ifdef DEBUG
# define FLAGS_IF(x) if (MyFunction((x)))
#else
# define FLAGS_IF(x) if(0)
#endif
I might do something like:
#ifdef DEBUG
const bool IS_RELEASE_MODE = false;
#else
const bool IS_RELEASE_MODE = true;
#endif
if (IS_RELEASE_MODE && MyFunction(expression))
{
...
}
This should get compiled out of release builds due to the fact that if (false && f()) is the same as if (false), which gets optimized out in most compilers.
That's if you're insistent on not using #ifdef on the inside of your code. Otherwise, I'd prefer the #ifdef DEBUG if (MyFunction(expression)) { ... } #endif that someone else posted.
Why can't you use the following?
#ifdef DEBUG
code for debug mode
#else
code for release mode
#endif
I generally try to avoid too much use of conditional compilation when possible.
For one, it's usually ugly and less readable.
But even more significantly, when projects use conditional compilation to turn debugging code on & off I have sometimes run into problems that the debugging code gets stale when it's disabled. Then when I want to actually use it debugging code, I turn it on and... Things. Don't. Build. Anymore.
The debug code may reference variables or functions that no longer exist, or things around the latent debugging code have otherwise changed enough that's it's just not syntactically valid anymore.
It can be really irritating.
So I've personally taken to avoiding conditional compilation to enable/disable debugging code in favor of using an enumeration or macro (that is still conditionally compiled) to use as the condition in an if statement. When compiled as an if (0) no runtime code gets generated - exactly as desired. But, the code is still compiled and syntax checked, so it's always at least syntactically correct.
#if NDEBUG // using the same standard macro that `assert()` uses
// use your own if NDEBUG doesn't make sense
enum {
DebugOn = 0
}
#else
enum {
DebugOn = 1
}
#endif
// ... elsewhere
if (DebugOn) {
// this always gets compiled, but if it's a release build
// the compiler will not emit anything...
}
As FryGuy mentioned, you can easily combine this with calling your MyFunction() if you like - in a release build, the function will not be called due to short-circuiting, which is the behavior you specified:
if (DebugOn && MyFunction( expression)) {
// this always gets compiled, but if it's a release build
// the compiler will not emit anything...
}
But personally, I'd probably use
if (DebugOn) {
if (MyFunction( expression)) {
// ...
}
}
Which I think helps call out a little more clearly (just a little) that this is a debug-only block.
This has the advantages of always being compiled and having no flow control hidden behind macros (which several other answers have mentioned as an evil).
How about something like this:
#ifdef DEBUG
#define FLAGS_IF(expr, block) { if (MyFunction(expr)) block }
#else
#define FLAGS_IF(expr, block)
#endif
You can use it like this:
FLAGS_IF(your_favourite_expression,
({
// some code
})
)