ifdef replacement in the Swift language
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Swift does not use C-style #ifdef and #ifndef macros for most conditional compilation tasks. The replacement is Swift's own #if system with built-in conditions such as os, arch, canImport, and custom compilation flags defined in build settings. For API availability at runtime, Swift uses if #available, which solves a different problem from compile-time exclusion.
Use Swift Conditional Compilation, Not the C Preprocessor
Swift supports compile-time conditions with directives such as:
- '
#if' - '
#elseif' - '
#else' - '
#endif'
A basic example:
This is the closest direct replacement for the old #ifdef DEBUG style.
The key difference is that Swift does not encourage arbitrary macro programming the way C does. The language offers a smaller, more structured set of compile-time conditions.
Built-In Conditions You Will Actually Use
Swift provides several useful conditions out of the box.
Operating system:
Architecture:
Simulator versus device:
Module presence:
These cover most real-world cases where developers coming from C or Objective-C would previously reach for #ifdef.
Define Your Own Flags
Custom flags in Swift are usually configured in the build settings rather than written in source headers.
In Xcode, add a value under Active Compilation Conditions, for example INTERNAL_BUILD. Then use it like this:
If you compile from the command line, you can pass a flag with -D.
This is the proper Swift replacement for many old #define FEATURE_X plus #ifdef FEATURE_X workflows.
if #available Solves a Different Problem
A common point of confusion is mixing compile-time conditions with runtime API availability.
If you need to check whether a device can call a newer API at runtime, use if #available, not #if.
Why the distinction matters:
- '
#ifremoves code at compile time based on build conditions' - '
if #availablekeeps both branches in the binary and chooses at runtime based on OS version'
These are not interchangeable.
A Practical Example
Suppose you want debug-only logging on iOS, but only when building an internal version.
That is expressive enough for most build-configuration cases without falling back to a macro-heavy style.
Prefer Normal Swift Design When Possible
Not every variation should become a compile-time flag. Sometimes a protocol, configuration object, or dependency injection is the better design.
Use compile-time conditions when the code genuinely differs by:
- platform
- build type
- available module
- target environment
Use ordinary runtime code when behavior can vary without changing what gets compiled.
Overusing compilation flags can make the codebase harder to test and reason about.
Common Pitfalls
A common mistake is trying to recreate the C preprocessor mentally and expecting arbitrary macro substitution. Swift does not work that way.
Another mistake is using #if when the real question is OS availability at runtime. That should be if #available.
People also forget that custom flags must be defined in build settings or passed with -D. Writing #if MYFLAG in source does nothing unless the flag exists.
Finally, canImport is often better than platform checks when the real dependency is the presence of a framework rather than the platform name itself.
Summary
- Swift replaces most
#ifdefuse cases with#if,#elseif,#else, and#endif - Built-in conditions such as
os,arch,targetEnvironment, andcanImportcover common compile-time decisions - Custom flags are added through
Active Compilation Conditionsin Xcode or-Don the command line - Use
if #availablefor runtime API availability checks, not as a replacement for compile-time flags - Prefer normal Swift design over conditional compilation when the behavior does not truly depend on build context
- Think in terms of compile-time conditions and runtime checks as separate tools with different purposes
Related reading
- ifdef replacement in the Swift language
- Ignore certain exceptions when using Xcode's All Exceptions breakpoint
- IllegalArgumentException navigation destination xxx is unknown to this NavController
- IllegalStateException Can not perform this action after onSaveInstanceState with ViewPager
- ImageView - have height match width?
- ImageView in circular through XML
- Immutable/Mutable Collections in Swift
- Impact of Xcode build options Enable bitcode Yes/No
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.