#ifdef replacement in the Swift language

2018-12-31 16:10发布

In C/C++/Objective-C you can define a macro using compiler preprocessors. Moreover, you can include/exclude some parts of code using compiler preprocessors.

#ifdef DEBUG
    // Debug-only code
#endif

Is there a similar solution in Swift?

15条回答
无色无味的生活
2楼-- · 2018-12-31 16:54

isDebug Constant Based on Active Compilation Conditions

Another, perhaps simpler, solution that still results in a boolean that you can pass into functions without peppering #if conditionals throughout your codebase is to define DEBUG as one of your project build target's Active Compilation Conditions and include the following (I define it as a global constant):

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

isDebug Constant Based on Compiler Optimization Settings

This concept builds on kennytm's answer

The main advantage when comparing against kennytm's, is that this does not rely on private or undocumented methods.

In Swift 4:

let isDebug: Bool = {
    var isDebug = false
    // function with a side effect and Bool return value that we can pass into assert()
    func set(debug: Bool) -> Bool {
        isDebug = debug
        return isDebug
    }
    // assert:
    // "Condition is only evaluated in playgrounds and -Onone builds."
    // so isDebug is never changed to true in Release builds
    assert(set(debug: true))
    return isDebug
}()

Compared with preprocessor macros and kennytm's answer,

  • ✓ You don't need to define a custom -D DEBUG flag to use it
  • ~ It is actually defined in terms of optimization settings, not Xcode build configuration
  • Documented, which means the function will follow normal API release/deprecation patterns.

  • ✓ Using in if/else will not generate a "Will never be executed" warning.

查看更多
十年一品温如言
3楼-- · 2018-12-31 16:55

After setting DEBUG=1 in your GCC_PREPROCESSOR_DEFINITIONS Build Settings I prefer using a function to make this calls:

func executeInProduction(_ block: () -> Void)
{
    #if !DEBUG
        block()
    #endif
}

And then just enclose in this function any block that I want omitted in Debug builds:

executeInProduction {
    Fabric.with([Crashlytics.self]) // Compiler checks this line even in Debug
}

The advantage when compared to:

#if !DEBUG
    Fabric.with([Crashlytics.self]) // This is not checked, may not compile in non-Debug builds
#endif

Is that the compiler checks the syntax of my code, so I am sure that its syntax is correct and builds.

查看更多
浪荡孟婆
4楼-- · 2018-12-31 16:57

![In Xcode 8 & above go to build setting -> search for custom flags ]1

In code

 #if Live
    print("Live")
    #else
    print("debug")
    #endif
查看更多
登录 后发表回答