#Ifdef Replacement in the Swift Language

What's the Swift equivalent of Objective-C's #ifdef __IPHONE_11_0?

The iOS 11 SDK comes with Swift 3.2 (or Swift 4), so you can use a Swift version check to accomplish the same thing:

#if swift(>=3.2)
if #available(iOS 11.0, *) {

}
#endif

Swift errors using #if, #endif

Ideally, limit the usage of #if as much as possible. Using preprocessor directives is always a bit of a code smell. In this case, you can simply use a boolean variable:

#if DEBUG
let debug = true
#else
let debug = false
#endif

Then simply use the variable:

var a = 0
var b = 0

...

else if debug && a == b {
}

In release mode the code will become unreachable and the optimizer will remove it anyway.

With a bit of imagination, we can find other solutions, for example, we can move the check to a function:

func isDebugCheck(a: Int, b: Int) -> Bool {
#if DEBUG
return a == b
#else
return false
#endif
}

or we can move the whole code to a separate function and replace if-else by a return (or continue, depending on you needs), e.g.:

if a == 7 {
...
return
}

#if DEBUG
if a == b {
return
}
#endif

if ...

Xcode 9.1 upgrade to Swift 4 breaks #ifdef

Previously, I was using the 'Other Swift Flags' build setting in Xcode to pass '-DXCODE_BUILD'. Apparently that setting doesn't work for Swift 4. The new setting that does work is 'Active Compilation Conditions' (it should be set to include XCODE_BUILD, no need for the -D flag).

Conditional exclusion of code in Swift

The issue was about replicating the configuration in the Other Swift Flags file in the form

-D option

Apparently Swift ignores the flags in the preprocessor field. Now it accepts ||, && and ! without any problem with syntax:

#if option || !option2
......
#elseif option3
......
#endif

How to translate the following code snippet from Swift to Objective-C?

I have managed to solve this problem with a workaround discussed here.

#if __clang_major__ >= 12
NSLog(@"My Objective-C language support is what Apple Clang/Xcode 12.x can support.");
#endif

Note that clang_major or clang_minor etc. variables resemble (almost same to) Xcode versions and need careful investigation before the usage.

Swift replacement for Objective-C macro

The easiest way is probably to take advantage of string interpolation and use:

func FLOG(message:String, method:String = __FUNCTION__) {
println("\(method): \(message)")
}

Then you usage is similar to:

FLOG("Illegal value: \(value)")

Having the method argument default to __FUNCTION__ means that it will normally be replaced with the calling function name. Other automatic variables that you could use include __FILE__, __LINE__ and __COLUMN__. Unfortunately __PRETTY_FUNCTION__ is no longer available.

If you want more control over the formatting of the message than string interpolation allows, take a look at this question which demonstrates simplifying access to printf-style formatting in Swift, and would let you do:

FLOG("Illegal value: %x" % [value])

See also this post from Apple that addresses using __FILE__ and __LINE__ in assert

Is there an #ifdef to distinguish between Xcode 6.4 and Xcode 7 beta in Swift?

no, as Swift imposes all "define" path must compile.
sorry but old good times of #ifdef are gone



Related Topics



Leave a reply



Submit