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

#ifdef DEBUG
    // Debug-only code
#endif

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


当前回答

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

#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

其他回答

Xcode 8及以上

使用Build设置/Swift编译器-自定义标志中的Active Compilation Conditions设置。

这是将条件编译标志传递给Swift编译器的新构建设置。简单地添加如下标志:ALPHA、BETA等。

然后使用如下编译条件进行检查:

#if ALPHA
    //
#elseif BETA
    //
#else
    //
#endif

提示:您也可以使用#if!ALPHA等。

在许多情况下,您实际上不需要条件编译;您只需要可以打开和关闭的条件行为。为此,您可以使用环境变量。这有一个巨大的优点,你实际上不需要重新编译。

您可以在方案编辑器中设置环境变量,并轻松地将其打开或关闭:

您可以使用NSProcessInfo检索环境变量:

    let dic = NSProcessInfo.processInfo().environment
    if dic["TRIPLE"] != nil {
        // ... do secret stuff here ...
    }

这是一个现实生活中的例子。我的应用程序只在设备上运行,因为它使用的是模拟器上不存在的音乐库。那么,如何在模拟器上拍摄我不拥有的设备的屏幕快照?没有这些屏幕截图,我无法提交到AppStore。

我需要假数据和不同的处理方式。我有两个环境变量:一个是当打开时,告诉应用程序在我的设备上运行时从真实数据生成假数据;另一个,当打开时,在模拟器上运行时使用假数据(而不是丢失的音乐库)。由于Scheme编辑器中的环境变量复选框,打开/关闭这些特殊模式很容易。另外一个好处是,我不会在我的App Store构建中意外使用它们,因为归档没有环境变量。

XCODE 9及以上

#if DEVELOP
    //print("Develop")
#elseif PRODUCTION
    //print("Production")
#else
    //
#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中使用不会生成“将永远不会执行”警告。

如Apple Docs中所述

Swift编译器不包含预处理器。相反,它利用编译时属性、构建配置和语言特性来实现相同的功能。因此,在Swift中不导入预处理器指令。

我已经通过使用自定义构建配置实现了我想要的目标:

转到项目/选择目标/构建设置/搜索自定义标志对于所选目标,使用-D前缀(不带空格)为调试和发布设置自定义标志为您的每个目标执行以上步骤

以下是检查目标的方法:

#if BANANA
    print("We have a banana")
#elseif MELONA
    print("Melona")
#else
    print("Kiwi")
#endif

使用Swift 2.2测试