I am trying to change an image for the two different versions of my app. Here is the code that i have tried so far.
- (void)viewDidLoad
{
[super viewDidLoad];
#ifdef LITE_VERSION
setImage:[UIImage imageNamed: #"30 Tap Game Logo Lite.png"];
#endif
}
You will need to configure your targets' Preprocessor Macros. If you select your target in Xcode and select Build Settings, then search for "preprocessor macros" you'll find the setting you need.
In your light version target (and only in that target) you'll need to add a macro like "LITE_VERSION=1". Then when you build the light version target LITE_VERSION will be defined.
You might also consider using #if LITE_VERSION instead of #ifdef LITE_VERSION just in case you ever want to explicitly turn off LITE_VERSION with #define LITE_VERSION=0.
If you're not sure whether or not your preprocessor macros were set up correctly, you can do something like this:
#ifdef LITE_VERSION
#error Light version is defined.
#else
#error Light version is not defined!
#endif
That will cause the preprocessor to generate an error clearly showing whether or not your macro is defined. (It will also stop the build process, so you can't leave that snippet in your code, but it might help you debug your target configurations.)
Related
Before swift I would define a set of schemes for alpha, beta, and distribution builds. Each of these schemes would have a set of macros that were defined to gate certain behaviors at the project level. The simplest example is the DEBUG=1 macro that is defined by default for all Xcode projects in the default scheme for the Run build. One could query #ifdef DEBUG ... and make decisions in the code accordingly, even compiling out non-necessary code.
It seems that this type of configurational gating is not as easy using swift, as macros are not supported. Can someone suggest a comparable approach, I don't care if the code is compiled out, per se. I would like to gate features based on build scheme, though.
In Swift you can still use the "#if/#else/#endif" preprocessor macros (although more constrained), as per Apple docs. Here's an example:
#if DEBUG
let a = 2
#else
let a = 3
#endif
Now, you must set the "DEBUG" symbol elsewhere, though. Set it in the "Swift Compiler - Custom Flags" section, "Other Swift Flags" line. You add the DEBUG symbol with the -D DEBUG entry.
(Build Settings -> Swift Compiler - Custom Flags)
As usual, you can set a different value when in Debug or when in Release.
I tested it in real code; it doesn't seem to be recognized in a playground.
We ran into an issue with not wanting to set swift compiler flags because we didn't want to have to set them and keep them up to date for different targets etc. Also, in our mixed codebase, we didn't want to make remember to set our flags appropriately all the time for each language.
For ours, we declared a file in ObjC
PreProcessorMacros.h
extern BOOL const DEBUG_BUILD;
In the .m
PreProcessorMacros.m
#ifdef DEBUG
BOOL const DEBUG_BUILD = YES;
#else
BOOL const DEBUG_BUILD = NO;
#endif
Then, in your Objective-C Bridging Header
#import "PreProcessorMacros.h"
Now, use this in your Swift codebase
if DEBUG_BUILD {
println("debug")
} else {
println("release")
}
This is definitely a workaround, but it solved our problem so I posted it here in the hopes that it will help. It is not meant to suggest that the existing answers are invalid.
More swifty solution to Logans method. Set -D DEBUG in Other Swift Flags of Swift Compiler - Custom Flags section in build settings of your target.
Then declare following method in global scope:
#if DEBUG
let isDebugMode = true
#else
let isDebugMode = false
#endif
Now use it as
if isDebugMode {
// Do debug stuff
}
For me, set the debug item of "Active Compilation Condition" to "DEBUG" worked.
Then using DEBGU key work in #IF DEBUG works in debug mode and #ELSE in release mode:
Select your target,
In Build Setting tab search for "Active Compilation Condition",
Set the value of its "Debug" item to "YourKeyWord",
Use simply as follow:
#if DEBUG
print("You'r running in DEBUG mode!")
#else
print("You'r running in RELEASE mode!")
#endif
Swift compiler directives
You can use next compiler directive
#if <some_key>
//logic 1
#else
//logic 2
#endif
//pre Xcode v8
Other Swift Flags(OTHER_SWIFT_FLAGS) = -D <some_key>
-D DEBUG
//from Xcode v8
Active Compilation Conditions(SWIFT_ACTIVE_COMPILATION_CONDITIONS) = <some_key>
DEBUG
I'm working in a mixed language code base where the obj-c code uses a macro to send debug messages to the console (and that macro relies on our debug preprocessor flag). I wanted to be able to call that same macro in the swift code...
I created a class method on one of my obj-c classes that is a wrapper around that macro.
I added that obj-c header to our bridge header file.
Now my swift code calls that class method as a "proxy" to the obj-c macro.
It's mildly annoying that I can't just call the macro straight up in the swift code, but at least now I only have one place in the project to worry about turning my debug flag on/off.
I should built and archive my application with Prod_URL and Stage_URL for our test team.
now i am using an Constant.h file and there is a code like;
//for stage
#define SERVICE_URL #"myStageUrl.com"
/*
//for prod
#define SERVICE_URL #"myProdUrl.com"
*/
And I always changing comment out lines to be able to build two different version of my app.
So now I wanna do it automatically.
I create two target like MyAppStage and MyAppProd. And I think I should write a Run Script for that to switch between these two #define lines. But I don't know how to write script.
Or are there any better way for that situation?
Thx,
If you have two separate targets you can place these defines in the project properties its self. To do that you go to your project properties. Click on the target you want to edit, click on the "Build Settings" tab and search for Preprocessor Macros. Define anything you want there and it will be visible for every class in that target.
Another option is to use the same Preprocessor Macros build setting and set a macro for STAGE. then in your Constant.h you can have something like:
//for stage
#ifdef STAGE
#define SERVICE_URL #"myStageUrl.com"
#else
//for prod
#define SERVICE_URL #"myProdUrl.com"
#endif
In your target for staging, add a preprocessor macro, something like STAGING_BUILD will do. Don't change the production target.
Now, in your code:
#ifdef STAGING_BUILD
//for stage
#define SERVICE_URL #"myStageUrl.com"
#else
//for prod
#define SERVICE_URL #"myProdUrl.com"
#endif
then only the required line will be compiled in based on the target selected to be built.
It is unclear to me when using compiler directives which of the below two code snippets is correct/preferred and why. It seems that most developers and Open Source projects I've seen use the first but I have seen the second used frequently as well.
#ifdef DEBUG
[self doSomethingOnlyWhenDebugging];
#endif
VERSUS
#if DEBUG
[self doSomethingOnlyWhenDebugging];
#endif
Which of the above code snippets is preferable for running code only while debugging and why? My guess is that the first will run if DEBUG is defined as TRUE or FALSE where the second will run only if DEBUG is defined and set to TRUE. Is that correct?
You are correct. #if DEBUG will not evaluate if DEBUG is defined as 0.
As for when to use each, you can stick to using #ifdef for anything where you only need to add code if the preprocessor definition is present, such as adding debug logging. If you need to inspect the value and go down different compilation paths, then I would use a 0 or 1. A good example of that is TARGET_IPHONE_SIMULATOR, which is always defined for an iOS project, but only 1 if you’re compiling for the simulator.
As I know, the finest choice is:
#ifndef DEBUG
NSLog(#"-1");
#elif DEBUG == 0
NSLog(#"0");
#else
NSLog(#"%d", DEBUG);
#endif
then, you will know #ifndef DEBUG is preferred above all others.
There is a simpler choice:
#if DEBUG == 0 // DEBUG is not defined or defined to be 0
// do sth
#else
// do sth
#endif
However, if -Wundef compiler flag is on, there might be a warning with #if DEBUG == 0.
You need to look at the code where DEBUG gets defined or not defined, and write your code accordingly. With DEBUG, you will find that it is either not defined, or defined with a value of 1. So either #if DEBUG or #ifdef DEBUG will work.
For #define's that are under your control, I recommend that you always define them, either with a value of 0 or 1. You can then use #if to check for the value, but you can also use them directly in an ordinary if statement or in an expression, which may make your code more readable. And since it is always defined, you can use "Jump To Definition" in Xcode to go to the place where it is defined and check how and why it is set. If instead you either #define or not #define the value, and it is not defined, then Xcode will have no idea where in your source code it is not defined. It also gives you a chance to look for misspelled uses. If "Jump to Definition" doesn't work, then you know you have spelled it wrong.
BTW Within an #if directive, any macro that is not defined is replaced by 0. So #if DEBUG will work if DEBUG is not defined, or if DEBUG is defined as 0, and it will not compile if DEBUG is defined as nothing - which will tell you what is wrong so you can fix it. From that point of view, using #if is better unless it doesn't compile.
I have an iOS Application that I am managing that has two targets.
This was done as both targets utilize 90% of the same code.
Each target has a specific Preprocessor Macro assigned to so blocks of code can be distinguished for each Target.
Everything compiles correct for both targets.
The problem though is that the xcode only auto compeletes and syntax highlights for the first taget.
For Example:
Target => "MainTarget" - Preprocessor Macro => TARGET_A=1
Target => "OtherTarget" - Preprocessor Macro => TARGET_B=1
Then if I have the following code:
#if TARGET_B
NSLog(#"Log Something %f", 3.5);
#else
NSLog(#"Log other stuff %i", 4);
#endif
Only NSlog(#"Log other stuff %i", 4); is correctly colored.
Compiling and Running works fine, but I'd like to visually know before building and launching that I have a typo.
As such it would be nice to be able to switch weither MainTarget or OtherTarget is the active code for the editor.
It seems that XCode no longer has that feature. Try changing the scheme next to the Stop button.
Source: Where is "Edit Active Target" in Xcode 4
I would like to do something similar to #ifdef __linux__, but with the bada SDK. Is there a constant defined by default?
Also, can I detect when I am compiling for the simulator?
You can, by checking the MingW Compiler's keyword, here's an interesting link that would point you in the right spot... so in theory you could have it this way
#ifdef __MINGW32__
/* we're in the simulator target */
#else
/* we're in the native target */
#endif
I use something like :
#ifdef SHP
# define CONFIG_SUPPORT_API_Osp 1 // bada
#endif
I wish there is also a define that tell sdk version or target api too ..
Use :
#ifdef _DEBUG
// Your code
#endif