How do I declare a debug only statement - objective-c

In C# I can use the following code to have code which only executes during debug build, how can I do the same in Xcode?
#if DEBUG
{
// etc etc
}
#endif

You can use
#ifdef DEBUG
....
#endif
You'll need to add DEBUG=1 to the project's preprocessor symbol definitions in the Debug configuration's settings as that's not done for you automatically by Xcode.
I personally prefer doing DEBUG=1 over checking for NDEBUG=0, since the latter implies that the default build configuration is with debug information which you then have to explicitly turn off, whereas 'DEBUG=1' implies turning on debug only code.

The NDEBUG symbol should be defined for you already in release mode builds
#ifndef NDEBUG
/* Debug only code */
#endif
By using NDEBUG you just avoid having to specify a -D DEBUG argument to the compiler yourself for the debug builds

DEBUG is now defined in "debug mode" by default under Project/Preprocessor Macros. So testing it always works unless you have a very old project.
However I hate the fact that it messes up the code indentation and not particularly compact. That is why I use another macro which makes life easier.
#ifdef DEBUG
#define DEBUGMODE YES
#else
#define DEBUGMODE NO
#endif
So testing the DEBUGMODE value is much more compact:
if (DEBUGMODE) {
//do this
} else {
//do that
}
My favourite:
NSTimeInterval updateInterval = DEBUGMODE?60:3600;

There is a very useful debugging technote: Technical Note TN2124 Mac OS X Debugging Magic
http://developer.apple.com/technotes/tn2004/tn2124.html#SECENV which contains lots of useful stuff for debugging your apps.
Tony

Related

Swift's canImport analogue in Objective-C

Swift 4.2 has a special condition canImport that helps developers to check whether a module can be imported in project. It was introduced in Swift 4.1.
Now I am working on iOS project written in Objective-C. I use modules, and for each target these modules are different. That's why I want to use something like that:
#if canImport(SomeModule)
#import SomeModule;
#endif
How can I solve this problem? Now I use different "Other C Flags" for each target, but I want to find more flexible solution.
This is a little late as an answer, but i came across this issue while working on a similar case.
I used the __has_include(<SomeModule/SomeModule.h>)
Importing your framework:
#if __has_include(<SomeModule/SomeModule.h>)
#import <SomeModule/SomeModule.h>
#define __HAS_SOME_MODULE_FRAMEWORK__
#endif
Later in your code :
- (void)doSomething {
#ifdef __HAS_SOME_MODULE_FRAMEWORK__
// with SomeModule framework
#else
// without SomeModule framework
#endif
}

Cocoa preprocessor exit file

I've seen some compilers that lets you stop reading the file where ever in the file you want
and I want to know if obj-c has such thing here's an example, so you can understand:
#ifndef __OBJC__ // or #if !defined(__OBJC__)
#exit // do not continue compiling this file!
#endif
No, you can't simply stop compilation in the middle of the file. You'd have to structure it this way:
#if __OBJC__
// the rest of the file
#endif

Xcode - conditional development or production mode

In searching for this I could only find info for other languages. I would like to know the best practice for writing conditional statments such as:
if (DEV_MODE){
//do something
}else{
//do the real stuff
}
And then setting DEV_MODE on or off in some global file so I only have to change that to on or off instead of changing code in multiple places. I have some ideas but am looking for advice on the best way to do this.
Try this:
#ifdef DEBUG
// do stuff
#endif
The current version of Xcode automatically sets this macro in new projects. Go to your projects Build Settings to make sure. If it's not there you have to add it yourself:
(This question is not related to Xcode.)
That said, instead of polluting your code with C-style IFs, you can use preprocessor directives to filter out debug and release mode. As far as I know, it's a common practice to define the DEBUG macro to 1 if in testing mode, and not to define it if in release mode. (Also, Xcode may define this for you, I've seen this behavior having been relied upon.) The reason is that the use of the preprocessor is more readable, since it doesn't get into the indentation, it's better separated from the code visually. To sum up, try
#ifdef DEBUG
// do debug stuff here
#else
// do release stuff here
#endif
One extra argument for preprocessor macros is that you can conditionalize the global namespace, which you couldn't within C code. I. e., with preprocessor macros, you can write
#ifdef DEBUG
int functionOne()
{
}
#else
char *functionTwo(int a)
{
}
#endif
You couldn't do this without the preprocessor.
Preprocessor variables are what you want, in your build configurations define a variable (DEV_MODE for example), and then use preprocessor checks like:
#if DEV_MODE
//dev mode code
#else
//non-dev mode code
#endif
In your project settings there is a section called "Preprocessor Macros". In that section you can add a string for your Debug build such as "DEV_MODE" or whatever you want. Then you can do your conditions you listed above and when your app gets built for "Release" or any other setting that does not contain your macro your check should fail.

How to do not write log on release mode in iOS?

In my memory, there's some code that can let the NSLog not work when released.
I don't want to remove my NSLog in my code.It helps a lot on debug mode.
So I want to find a way that can leave them in my code, and also don't slow down the application when released.
Thanks for your help~~
A common way to remove all NSLog(…) call in a release is to create a macro that is between conditional preprocessor macro and compiles to nothing, something like this:
#ifdef RELEASE
# define NSLog(...) //remove loggin in production
#endif
Put this code in a .h file that is included in every other file, like a Defines.h that is #include'd in the prefix header (.pch).
RELEASE should be a preprocessor macro defined against the Release configuration in the "Build Settings" tab of your target.
Related Questions
Is it true that one should not use NSLog() on production code?
How to print out the method name and line number and conditionally disable NSLog?
You will need to replace NSLog with a custom macro.
Put for instance
#ifdef DEBUG
# define DLog(...) NSLog(__VA_ARGS__)
#else
# define DLog(...) /* */
#endif
#define ALog(...) NSLog(__VA_ARGS__)
in your prefix pch file.
Use ALog for cases where you always want log output regardless of the state of the debug flag, and DLog for log only in debug mode.
Source

Change code based on Xcode build type

When I build my app as an Adhoc, I would like to set a specific var to YES. Is it possible for my code to know what it is being built for, and change a part of the code if it is for debug or adhoc?
In the Build Settings for a target you can set preprocessor symbols based on the build type you are doing, then in your code you can test for these using #ifdef/#endif, or to test for specific values you can use #if. Look up the preprocessor in the docs.
For example, this is commonly used to define the symbol DEBUG for debug builds and then conditionally include code:
#ifdef DEBUG
NSLog(#"The value of ix is %d", ix);
#endif