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

#ifdef DEBUG
    // Debug-only code
#endif

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


当前回答

XCODE 9及以上

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

其他回答

这是基于Jon Willis的答案,该答案依赖于断言,该断言仅在调试编译中执行:

func Log(_ str: String) { 
    assert(DebugLog(str)) 
}
func DebugLog(_ str: String) -> Bool { 
    print(str) 
    return true
}

我的用例是记录打印语句。以下是iPhone X上发布版本的基准:

let iterations = 100_000_000
let time1 = CFAbsoluteTimeGetCurrent()
for i in 0 ..< iterations {
    Log ("⧉ unarchiveArray:\(fileName) memoryTime:\(memoryTime) count:\(array.count)")
}
var time2 = CFAbsoluteTimeGetCurrent()
print ("Log: \(time2-time1)" )

打印:

Log: 0.0

看起来Swift 4完全消除了函数调用。

XCODE 9及以上

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

Xcode 8及以上

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

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

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

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

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

在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.4.1创建的Swift项目中,Swift 4.1

#if DEBUG
#endif

默认情况下工作,因为在预处理器宏中,Xcode已设置DEBUG=1。

因此,您可以使用#if DEBUG“开箱即用”。

顺便说一句,苹果的《Swift编程语言4.1》一书(编译器控制语句一节)中写了如何使用条件编译块,而如何编写编译标志以及Swift中C宏的对应内容,则在另一本苹果的《将Swift与Cocoa和Objective C结合使用》一书中(预处理器指令一节)

希望未来苹果会为他们的书写更详细的内容和索引。