在C/C++/Objective C中,可以使用编译器预处理器定义宏。此外,您可以使用编译器预处理器包含/排除代码的某些部分。

#ifdef DEBUG
    // Debug-only code
#endif

Swift中有类似的解决方案吗?


当前回答

是的,你能做到。

根据Apple文档,在Swift中,您仍然可以使用“#if/#else/#endif”预处理器宏(尽管更受限制)。下面是一个示例:

#if DEBUG
    let a = 2
#else
    let a = 3
#endif

现在,您必须在其他地方设置“调试”符号。在“Swift编译器-自定义标志”部分的“其他Swift标志”行中设置它。您可以使用-D DEBUG条目添加DEBUG符号。

通常,您可以在“调试”或“发布”中设置不同的值。

我在真实代码中测试了它,它工作了;不过,在操场上似乎认不出它。

你可以在这里阅读我的原始帖子。


重要提示:-DDEBUG=1不起作用。只有-D DEBUG有效。编译器似乎忽略了具有特定值的标志。

其他回答

在GCC_PREPROCESSOR_DEFINITIONS构建设置中设置DEBUG=1后,我更喜欢使用函数进行以下调用:

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

然后,只需在此函数中包含我希望在调试构建中省略的任何块:

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

与以下各项相比的优势:

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

是编译器检查我的代码的语法,所以我确信它的语法是正确的,并进行编译。

XCODE 9及以上

#if DEVELOP
    //print("Develop")
#elseif PRODUCTION
    //print("Production")
#else
    //
#endif

有一些处理器接受一个参数,我在下面列出了它们。您可以随意更改参数:

#if os(macOS) /* Checks the target operating system */

#if canImport(UIKit) /* Check if a module presents */

#if swift(<5) /* Check the Swift version */

#if targetEnvironment(simulator) /* Check envrionments like Simulator or Catalyst */

#if compiler(<7) /* Check compiler version */

此外,您可以使用任何自定义标志,如DEBUG或您定义的任何其他标志

#if DEBUG
print("Debug mode")
#endif

isDebug常量基于活动编译条件

另一个可能更简单的解决方案是,将DEBUG定义为项目构建目标的Active Compilation Conditions之一,并包含以下内容(我将其定义为全局常量):

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

isDebug常量基于编译器优化设置

这个概念建立在kennytm的答案之上

与kennytm相比,其主要优势在于它不依赖于私有或未记录的方法。

在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
}()

与预处理器宏和kennytm的答案相比,

✓ 您不需要定义自定义的-D DEBUG标志来使用它~它实际上是根据优化设置定义的,而不是Xcode构建配置✓ 已记录,这意味着该函数将遵循正常的API发布/弃用模式。✓ 在if/else中使用不会生成“将永远不会执行”警告。

Xcode 8对ifdef替换进行了重大更改。即使用主动编译条件。

请参阅Xcode 8发行说明中的构建和链接。

新建生成设置

新设置:SWIFT_ACTIVE_COMPILATION_CONDITIONS

“Active Compilation Conditions” is a new build setting for passing conditional compilation flags to the Swift compiler.

以前,我们必须在OTHER_SWIFT_flags下声明条件编译标志,记住在设置前加上“-D”。例如,要有条件地使用MYFLAG值进行编译:

#if MYFLAG1
    // stuff 1
#elseif MYFLAG2
    // stuff 2
#else
    // stuff 3
#endif

要添加到设置的值-DMYFLAG

现在我们只需要将值MYFLAG传递到新设置。是时候移动所有这些条件编译值了!

有关Xcode 8中更多Swift Build Settings功能,请参阅以下链接:http://www.miqu.me/blog/2016/07/31/xcode-8-new-build-settings-and-analyzer-improvements/