Swift 編譯器指令與巨集 (Compiler Directives & Macros)

Swift 提供了一系列以 # 開頭的編譯器指令,用來控制編譯過程、發出警告或錯誤,以及使用強大的巨集 (Macros) 功能。

條件編譯 (Conditional Compilation)

使用 #if#elseif#else#endif 來根據不同的條件編譯程式碼。這在跨平台開發 (iOS vs macOS) 或區分 Debug/Release 模式時非常有用。

檢查作業系統

#if os(iOS)
    print("Running on iOS")
    let color = UIColor.red
#elseif os(macOS)
    print("Running on macOS")
    let color = NSColor.red
#else
    print("Running on other system")
#endif

檢查模組是否可匯入

這在開發 Swift Package 或 Library 時特別有用,可以根據使用者是否有安裝某個依賴來決定是否編譯相關程式碼。

#if canImport(SwiftUI)
import SwiftUI
#endif

檢查編譯模式

#if DEBUG
    print("Debug mode: 開啟詳細 Log")
#else
    print("Release mode: 關閉 Log 以優化效能")
#endif

診斷指令 (Diagnostics)

你可以在編譯時期手動觸發警告或錯誤。這對於標記「待辦事項」或「廢棄 API」非常有用。

  • #warning("message"): 產生黃色警告,但編譯會繼續。
  • #error("message"): 產生紅色錯誤,編譯會停止。
func incompleteFunction() {
    #warning("TODO: 記得實作這個函式")
}

#if os(watchOS)
    #error("目前尚未支援 watchOS")
#endif

來源位置 (Source Location)

這些指令在編譯時會被替換成當前的檔案資訊,常用於自定義 Debug Log 系統。

  • #file: 檔案路徑 (String)
  • #line: 行號 (Int)
  • #function: 函式名稱 (String)
func log(_ message: String, file: String = #file, line: Int = #line) {
    print("[\(file):\(line)] \(message)")
}

巨集 (Macros)

Swift 5.9 引入了強大的 Macros 功能,允許在編譯時期生成程式碼。最常見的例子就是 SwiftUI 的 #Preview

#Preview

取代了舊有的 PreviewProvider,讓預覽語法更簡潔。

#Preview {
    ContentView()
}

巨集種類

  1. Freestanding Macros (獨立巨集):以 # 開頭,像 #warning#Preview。它們通常產生一個值或一段程式碼。
  2. Attached Macros (依附巨集):以 @ 開頭,像 @Observable, @Model (SwiftData)。它們依附在宣告 (Class/Struct) 上,為其添加功能。
Macros 的底層實作比較複雜 (需要另一個 Target),但身為使用者,我們通常只需要知道如何使用它們 (#@) 即可。