I'm developing an iOS app with Swift 2 and, like most developers, I have a staging and a production environment, with different servers, URL and settings.
I'm looking for a way to quickly switch between the two configurations as I'm developing the app.
On Android I could use build types and flavors to solve this problem.
I've read a lot of guides around the web but all of them were in Obj-C and relied on the macro preprocessor and the #ifdef that was available in Obj-C but isn't in Swift.
There are no clear guides on how to do this in swift and, being a total beginner, I'm not even sure where to start looking.
To recap: what I'm looking for it's a way to switch between two configurations (ex 2 property list files) and to reference the settings contained in those configurations from my code, based on the build I've selected.
You can add a user defined setting in Target's settings with different values for each scheme (Debug, Release, Ad-Hoc, AppStore etc) and use the user defined variable in info.plist file (or as you call it configurations).
Check answer to this question. Although the question is specific to Facebook App Id setup, the answer applies to any generic setting.
Once you have correct data in info.plist you can directly use it in code.
Related
In my project there is a variable(Int) value that I want to be different for development and Ad-Hoc/Production because it's hard to test app with large number(100) for that value, so I changed it to 3 to test but now problem is that I have to build app frequently and some time I forgot to change the value back to 100 so is there any way to make this process automated ?
Use different build configurations as described here: http://limlab.io/swift/2016/02/22/xcode-working-with-multiple-environments.html
Targets are usually used for different apps sharing the same code base. For example: Lite and Pro versions of an application or Watch extension etc.
Update:
https://developer.apple.com/library/content/featuredarticles/XcodeConcepts/Concept-Targets.html
A target specifies a product to build and contains the instructions for building the product from a set of files in a project or workspace.
As I already mentioned, targets are usually used for different products which behave different. In your case you duplicate build setting, phases etc. for a single variable you want to be different.
https://developer.apple.com/library/content/featuredarticles/XcodeConcepts/Concept-Build_Settings.html
A build setting is a variable that contains information about how a particular aspect of a product’s build process should be performed.
It is quite enough to manage "different environments" for a single target in order to achieve what you want.
I have an IOS app which holds lot of Configuration settings to use the app and also this app is used in 5 warehouses, settings will be differ from one warehouse to another warehouse. So it becomes more painful for the users using this app.. Even ever they install the app then need to set the configuration settings.
So my problem is If i hardcode the settings value, it is very difficult to maintain the code for all the different warehouse. if i do small change in my app have to change in all of the 5 source code.. Even if i decide to maintain 1 code .. i have to change the setting value every time before setting the build.. It is more painful for me.
so my question is..
Is there any way to run a app and set values in configuration settings. And generate this setting app as a build ?? i don't know it will workout or not please share me some ideas..
If I understand correctly, you want to have 1 source code and there is possibility to create different Targets. Each target can have it's own configuration plist file and you can set also different preprocessor macros for each target.
How to use preprocesor macros you can see here: How can I differentiate between multiple targets in xcode at runtime
How to create targets you can see here: Add preprocessor macro to a target in xcode 6
One more possibility (besides targets) is to create a shared library and if you want to apply some configs after installation you can prompt user to download one from a server (for instance)
Yes, you can create different schemas.
For example, you can create an application for Development, Staging, Production.
You can have configurations in plist file and make it variable according to the schemas.
When your application opens it will take the values according to the schema with which it was built.
Follow this guide to create different schemas.
Also, you can integrate Fastlane to generate builds easily with different schemas with simple commands.
Yes you can have one app with different targets and schema. Then just google it there's many articles about.
I'm making an app that has two targets :
Premium
Lite
Basically in my architecture, only the json config file that determines which assets are displayed on a version is different.
So let's say the premium app should load "config.json" and the lite version should load "config-lite.json".
I only need this string but I'm completely lost among the techniques used to differentiate targets (often dev and prod).
My projet uses cocoa pods, should I (can I) use this to provide an environment variable ?
Do you do this using a plist file ? Or a preprocessor macro ?
Considering the update of this post, what is the workaround for preprocessor macros in swift ?
This (great) article seems to sum up very well what I need to do but the syntax of the preprocessor macros seem to no longer work, am I right ?
I'm sorry that I don't have code to provide, I'm just trying to establish a best practice that hopefully would help other developers !
I am deploying an iOS application in both US and China. App behaves pretty much the same but has slightly different logic. For example: we use email to register account but use phone number in China. Other than this obviously the languages used in app are different.
We are going to submit two different apps to US and China app store but we have this problem: two versions share considerable amount of code base(95%). That being said if in the future we ever need to add future to the app we have to manually migrate changes since we won't be able to use git(I assume so because they are different projects right?). This is surely not desirable. But by now I see no way to go around it.
Can any one offer any suggestions about approaching such issue? Maybe there is a git trick? Or we should not use two different projects in the first place? If not, what's the better way?
Thanks in advance.
Per our discussion, it is suggested to use Targets in the same project, the code is reused and can be checked in to one repo. Following is what I would do to maintain multiple Targets within the same project.
In Target US Build Settings, Preprocessor Macros, add following:
TARGET='TARGET_US'
In Target China Build Settings, Preprocessor Macros, add following:
TARGET='TARGET_CN'
Then in code, use preprocessors to check:
#define STRINGIZE(str) #str
#define STRINGIZE_MACRO(str) STRINGIZE(str)
#ifdef TARGET
if (STRINGIZE_MACRO(TARGET)=="TARGET_US") {
// US app logic goes here
} else if (STRINGIZE_MACRO(TARGET)=="TARGET_CN") {
// China app logic goes here
}
#endif
Also just want to point out that there is a way of associating Compiled source files with Targets, it is found in Build Phases. You can make a selection of code files that is needed to compile. E.g for Target US, Add main-us.m and USAppDelegate.m for compilation, for Target China use main-china.m and ChinaAppDelegate.m.
I wish to use Xcode's schemes to determine what server to run my app against. I have an app that fetches its information from a server. Like most people I have a development server, a staging server and a production server.
I wish to create a scheme for each of these where Xcode will inject the correct URL. Do I duplicate the run scheme and add environmental variables? Is this the best way to do things, I don't particularly wish to have #ifdef's in my server class and setting it in code each time I change server. Can anyone point me in the right direction please?
FYI: I'm using Xcode 5.0.2 iOS7 SDK.
[EDIT] Everyone gave some great suggestions but I feel #redent84 answer best suits my needs. Though I found it interesting that none actually suggested using different schemes. [/EDIT]
I recommend you to create different XCode Targets for each environment. I recommend you to change the App Identifier of the Apps, for example, the production app would be com.mycompany.App and the DEVEL version would be com.mycompany.App-DEVEL. This way you can track the Apps separately in HockeyApp or TestFlight, and you can have both applications in the same device at the same time.
Then, add Preprocessor Macros that define the environment for every target. DEVEL for development, for example.
If the URL is hardcoded, simply add a #ifdef instruction to choose the URL:
#ifdef DEVEL
#define ENDPOINT_URL #"http://develserver:8080/EndPoint"
#elif defined(STAGING)
#define ENDPOINT_URL #"http://stagingserver:8080/EndPoint"
#else
#define ENDPOINT_URL #"http://app.mycompany.com/EndPoint"
#endif
This way is less error-prone to distribute a development version, easier to maintain and allows you to add custom code to different versions. For example, you may want to include the version number in the login screen or show alert dialogs for development, but not for distribution version.
Use a key in the plist (for each schema, eg: URL_TO_USE), use define to create a 'shortcut' to get the value.
#define MyURL [[NSBundle mainBundle] objectForInfoDictionaryKey:#"URL_TO_USE"]
EDIT
You must have multiple targets. Each target should point to a different .plist file. See:
How to configure independent sets of runtime settings in XCode
I handle this by setting custom pre-processor defines for each scheme.