Swift Platform Compilation Conditions

Mar 13, 2023#swift#compiler

Swift compiler supports platform compilation conditions on whether to build certain parts of the code. Unlike regular if and else which execute at runtime, #if and #else are checked at compile time.

Platform condition Valid arguments
os() macOS, iOS, watchOS, tvOS, Linux, Windows
arch() i386, x86_64, arm, arm64
swift() >= or < followed by a version number
compiler() >= or < followed by a version number
canImport() A module name
targetEnvironment() simulator, macCatalyst

The version number for the swift() and compiler() platform conditions consists of a major number, optional minor number, optional patch number, and so on, with a dot (.) separating each part of the version number. There must not be whitespace between the comparison operator and the version number.

The version for compiler() is the compiler version, regardless of the Swift version setting passed to the compiler.

The version for swift() is the language version currently being compiled. For example, if you compile your code using the Swift 5 compiler in Swift 4.2 mode, the compiler version is 5 and the language version is 4.2.

The argument for the canImport() platform condition is the name of a module that may not be present on all platforms. The module can include periods (.) in its name. This condition tests whether it’s possible to import the module, but doesn’t actually import it.

You can combine and negate compilation conditions using the logical operators &&, ||, !, and parentheses for grouping.

Each statement in the body of a conditional compilation block is parsed even if it’s not compiled. However, there’s an exception if the compilation condition includes a swift() or compiler() platform condition: The statements are parsed only if the language or compiler version matches what is specified in the platform condition. This exception ensures that an older compiler doesn’t attempt to parse syntax introduced in a newer version of Swift.

#if os(iOS) || os(tvOS) || os(watchOS)
// use UIColor
#else
// use NSColor
#endif

#if canImport(UIKit)
// iOS, tvOS, and watchOS – use UIColor
#elseif canImport(AppKit)
// macOS – use NSColor
#else
// all other platforms – use a custom color object
#endif

// Test for a simulator destination
#if (arch(i386) || arch(x86_64)) && (!os(macOS))
  print("Simulator")
#else
  print("Device")
#endif

// More restrictive test for iOS simulator
// Adjust the os test for watchOS, tvOS
#if (arch(i386) || arch(x86_64)) && os(iOS)
  // iOS simulator code
#endif

#if targetEnvironment(simulator)
  // Simulator!
#endif