When you work on white branding apps. The target membership is an issue to expand for different UIs and logics which only apply for specific targets. We have to think about how to separate them in the same code base (Xcode Workspace).
Luckily Xcode build compiler supports us variables to do so. It says Macro Preprocessor. We basically use a lot about Macro on top of our header like below:#define PI 3.1415
And in scope of this post, I’ll limit about target as white branding apps. If you don’t familiar with Macro Preprocessor, I prefer to scroll to the end of page to download sample app and follow up this post for easy understanding.
So, in the end we will have something like this.
#if target
//handle logic for target membership classes
#elif target2
// Handle logic for target 2 membership classes
#else
// handle logic for common, applies for both targets
#endif
What is Target Membership and its issues:
Let say I have 3 classes:
MyCustom -> MacroDemo member
MyCustom2 -> MacroDemo2 member
Common -> MacroDemo and MacroDemo2 member
It means that only target member could access and instant to its classes. We absolutely get error from compiler when we try to access from class that non-membership.
How to define macro processor, especially for target?
Xcode -> TARGETS -> Build Settings -> type: Processors Macros -> Type the macro name you expected. And set equal to 1
The name should be unique for each target. For example the MacroDemo2 we will have MacroDemo2_target=1
So. In use, this will be like below. Compiler error is gone, it only access to right classes membership inside block
Important: It’s still not enough to make it works perfectly. Especially in Swift, there is an exception that you have to take care:
Inside Xcode -> TARGETS -> Build Settings -> Active Compilation Condition
Set same macro name with Preprocessor. But without equal to 1
Those are for Xcode settings. However, if you’re using xcodebuild for doing CI for example, here are variable name:
Macro Preprocessor: GCC_PREPROCESSOR_DEFINITIONS
Active Compilation Conditions: SWIFT_ACTIVE_COMPILATION_CONDITIONS
So, the command will be:
xcodebuild -workspace <your workspace> -scheme <your scheme> GCC_PREPROCESSOR_DEFINITIONS=<your definition> SWIFT_ACTIVE_COMPILATION_CONDITIONS=<your definition>
Notes: It’s a bit tricky to use Macro inside implementation because complier will ignore your classes/files during compile time. In other words, if you’re using a specific class (let say you changes your mind for new white branding to re-use some class but has added to Macro block, your app will crash due to non-accessible. So, make sure you really know which class is used for specific targets only or add #warning on top of function in order to adjust later.
You could find the sample project here: MacroSample
Cheers!