swift - macro - xcode#if




Swift語言中的#ifdef替換 (8)

Xcode 8及以上

使用編譯 設置/ Swift編譯器中的 活動編譯條件設置- 自定義標誌

  • 這是將條件編譯標誌傳遞給Swift編譯器的新構建設置。
  • 簡單添加像這樣的標誌: ALPHABETA

然後用這樣的編譯條件檢查它:

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

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

在C / C ++ / Objective-C中,您可以使用編譯器預處理器定義一個宏。 此外,您可以使用編譯器預處理器來包含/排除某些代碼部分。

#ifdef DEBUG
    // Debug-only code
#endif

Swift中有類似的解決方案嗎?


基於活動編譯條件的調試常量

另一個也許更簡單的解決方案仍然會導致一個布爾值,您可以將其傳遞到函數中,而不必在整個代碼庫中使用#if條件,這就是將DEBUG定義為您的項目構建目標的Active Compilation Conditions並包含以下內容(我將其定義為全球常數):

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

基於編譯器優化設置的調試常量

這個概念建立在肯尼特姆的答案之上

比較兩者的主要優點是,這不依賴私人或無證方法。

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發布/棄用模式。

  • ✓使用in if / else 不會生成“永不執行”警告。



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

是編譯器檢查我的代碼的語法,所以我相信它的語法是正確的,並建立。


從Swift 3.1開始,如果你只需要檢查代碼是用調試還是發布配置構建的,就可以使用內置函數:

  • _isDebugAssertConfiguration() (優化設置為-Onone時為-Onone
  • _isReleaseAssertConfiguration() (優化設置為-O時為true) (不適用於Swift 3+)
  • _isFastAssertConfiguration() (優化設置為-Ounchecked時為-Ounchecked

例如

func obtain() -> AbstractThing {
    if _isDebugAssertConfiguration() {
        return DecoratedThingWithDebugInformation(Thing())
    } else {
        return Thing()
    }
}

與預處理器宏相比,

  • ✓您不需要定義一個自定義的-D DEBUG標誌來使用它
  • 〜它實際上是根據優化設置來定義的,而不是Xcode構建配置
  • ✗未記錄,這意味著可以在任何更新中刪除該函數(但由於優化器會將這些函數變為常量,所以它應該是AppStore安全的)

  • ✗使用in if / else將始終生成“永不執行”警告。


我的Xcode 8的兩美分:

a)使用-D前綴的自定義標誌正常工作,但...

b)使用更簡單:

在Xcode 8中有一個新的部分:“有效編譯條件”,已經有兩行,用於調試和發布。

只需添加您的定義WITHOUT -D


正如Apple Docs所述

Swift編譯器不包含預處理器。 相反,它利用編譯時屬性,構建配置和語言功能來實現相同的功能。 因此,Swift中不會導入預處理器指令。

我已經設法通過使用自定義生成配置來實現我想要的功能:

  1. 轉到您的項目/選擇您的目標/構建設置/搜索自定義標誌
  2. 對於您選擇的目標,使用-D前綴(無空白)設置您的自定義標誌,用於調試和發布
  3. 針對每個目標執行上述步驟

以下是你如何檢查目標:

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

使用Swift 2.2進行測試


沒有Swift預處理器。 (首先,任意代碼替換會破壞類型和內存安全性。)

不過Swift的確包含了構建時配置選項,所以你可以有條件地包含某些平台的代碼或構建樣式,或者響應你用-D編譯器參數定義的標誌。 但與C不同,代碼的條件編譯部分必須在語法上完整。 在使用Swift With Cocoa和Objective-C中有一部分內容

例如:

#if os(iOS)
    let color = UIColor.redColor()
#else
    let color = NSColor.redColor()
#endif




preprocessor-directive