Assign a static constant at build time ios xcode - ios

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.

Related

How can I differentiate between multiple targets in xcode at runtime

Working on an old objective c application where in I need to create multiple targets. Question is how do I differentiate between multiple targets run time in the code and accordingly I need to load the resources from bundle.
Project > Build Settings > Preprocessor Macros
define there different macros for different targets e.g.:
TARGET_1
TARGET_2
and in code you can diferenciate it like this:
NSString *pathToMyResource = nil;
#ifdef TARGET_1
pathToMyResource = #"pathToMyResourceForTarget1";
#else
pathToMyResource = #"pathToMyResourceForTarget2";
#endif
EDIT: added swift syntax
#if DEBUG
let apiKey = "KEY_A"
#else
let apiKey = "KEY_B"
#endif
see here: Swift 3: how to use PREPROCESSOR Flags (like `#if DEBUG`) to implement API keys?
You can use #matloob's answer. Below is an another approach.
You can also use Preprocessing for differentiating among targets.
Please have a look at following tutorial. This may also help you.
Reference :
Target Differentiation dynamically - Appcoda

Setup different target for using different constant in Xcode

I know maybe a question is duplicated, but where I can check information. How to setup different targets to build with different bundle name etc.
Right now I know of course how to create different targets in Xcode, it is very simple to copy it from example from first target that was created automatically when I created project.
But I also have Constant.h and Constant.m files. I want to handle constants depend on which target I build for.
Let's say when build for target A I need to setup NSString const *toEmail = #"a#test.com", but in case if I build for the target B then toEmail = #"b#test";
Do I need to create two difference Constant files say ConstantA.m and ConstantB.m or maybe there is another best practice here. I don't want to recreate a wheel )
I setup Preprocessor Macro in target build settings for just one target. (For Example: TARGET_B)
And in code i check using
// Check if it's target B:
#if TARGET_B
NSString const *toEmail = #"b#test.com"
#else
NSString const *toEmail = #"a#test.com"
#end

Change Image Based on Target

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.)

In absence of preprocessor macros, is there a way to define practical scheme specific flags at project level in Xcode project

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.

iOS: How to add conditionality based on Project Target

I am building a project that will eventually be compiled to make 4 slightly different applications. The main change I have to make are image changes, but I also want to change a few UILabels as well.
I know that I could create multiple XIB files and modify them to be attached to each target, but I would is there a way to use a macro #define if to detect the name of the target?
Example: Project: Project1
Targets: TargetA, TargetB
#define if Target = TargetA{
label.text = #"This is targetA";
}
Is this possible?
Thanks!
I found an easy way to do this... you can access the bundle identifier which is unique for each target:
NSLog(#"%#", [[NSBundle mainBundle] bundleIdentifier]);
C preprocess macro will accomplish this feature.
In Xcode:
TARGET->Build Settings->Preprocess Marcos
And your source code:
#if DEBUG
// debug build
#else
// release build
#endif
This is already defined macro. You can define your own macros in all project targets.

Resources