i need to perform some actions when i am in the Debug mode, precisely, when i am in the debug mode, i want to add a button to my interface:
#ifdef DEBUG
NSLog(#"Some actions, add button and assign an action, etc.");
#else
//Do another operations
#endif
However, this doesn't appear to work even with a simple NSLog just i put to test my debug mode.
Am i missing something? Thanx in advance.
Related
I am developing a framework that connects to a hard coded url. I'd like to be able to change that url in automated tests. I adding the following to my umbrella header:
#ifdef DEBUG
- (void)setServerUrl;
#endif
I thought that if I build the framework in -configuration Release mode, the preprocessor would delete the method declaration from the code, which is what I want.
So, maybe my approach was wrong to begin with, or it was right but the implementation wasn't. In any case, how do I expose a method in DEBUG mode only? Is it possible?
Don't put this method in public header.
In yours automated test add category, that makes this method visible for them.
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.
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
I'm new to Cocoa/macOS programming. I just found out that NSUserDefaults can be used to change application/system settings, like the way the defaults command does.
But I don't know how to cause these settings to update.
e.g., I use NSUserDefaults to set the dock size to 32, and synchronize the setting. But the dock retains the old setting.
Even when I use defaults write com.apple.dock tilesize 32 to change its size, it won't be updated until I logout and login.
Is there any other technology to notify the dock to get the update? I know that System Preferences can do that.
Thank you!
The Mac OS X dock doesn't reload its settings until it is killed and restarted. In the same way that you'd have to change its settings manually via the terminal (defaults write com.apple.dock tilesize 32; killall Dock), you have to do that in code. So, while you've written the defaults portion of the code, you have to write the kill portion:
NSRunningApplication *dock = [NSRunningApplication runningApplicationWithBundleIdentifier:#"com.apple.dock"];
[dock terminate];
If you want to do this without killing the dock, sorry, but you're out of luck. While there might be a hidden API to force the dock to reload its settings on the fly, in all my searching I have never found any hints of how one can do this (there are no notifications posted on the hidden distributed notification center that most applications to interact with one another).
With the magic of the Xcode debugger and some formatted disassembly, I've created this short header file you can paste into your code (GitHub gist is here). Function names are hopefully self-explanatory.
// TO USE THESE INTERFACES, you MUST link against ApplicationServices.framework.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// Boolean preferences
extern void CoreDockSetLaunchAnimationsEnabled(bool enable);
extern void CoreDockSetMagnificationEnabled(bool enable);
extern void CoreDockSetAutoHideEnabled(bool enable);
extern void CoreDockSetMinimizeInPlace(bool enable);
// Sets other preferences such as whether the indicators below the app icons are shown
// 'preferenceDict' is a CFDictionary containing a magic key value
// Will require further inspection of Dock.prefpane to find all the keys
// (I haven't noted them down)
extern void CoreDockSetPreferences(CFDictionaryRef preferenceDict);
#ifdef __cplusplus
} // extern "C"
#endif
Preferences updated in this way are reflected instantaneously, because these functions actually messagethe "com.apple.dock" mach service internally.
Have fun!
PLEASE NOTE: These are private system APIs. Any apps submitted to the Mac App Store that use these APIs will be rejected. On another note, if you have no App Store intentions, there's no harm in using these interfaces. They appear to have existed since the very dawn of Mac OS X, and it's highly improbable they'll be disappearing in the near future, if ever.
You can use AppleScript to set some of the properties of the dock by scripting System Preferences, you may want to take a look at seeing if you can take that approach instead? Maybe call some AppleScript from your app?
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