iPhone #ifdef directive not working as expected - iphone

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

Related

How to indicate that code needs to be removed... eventually

Consider an app that needs to be compatible with iOS 5 and iOS 6.
Is there a way to mark the code that is there purely for iOS 5 compatibility, so that it appear as a compile error (or warning) when -eventually- the deployment target changes to iOS 6?
Something like this:
#IF_DEPLOYMENT_TARGET_BIGGER_THAN_IOS_5
#OUTPUT_ERROR_MESSAGE
#ENDIF
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
If not, what is the best alternative?
Try this:
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000
#warning This pre-6.0 code isn't needed anymore
#endif
- (BOOL)shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)toInterfaceOrientation {
return YES;
}
This code will cause a compiler warning once the Deployment Target is set to 6.0 or later.
#define MY_CONDITIONAL_DEPRECATED_ATTRIBUTE __deprecated
use it on all methods BUT until you need it turn it quiet
#define MY_CONDITIONAL_DEPRECATED_ATTRIBUTE
Consider looking at how Apple marks that sort of thing in their framework classes. It seems they're making use of the Availability.h and AvailabilityInternal.h classes in the SDK.

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.

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

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

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.