Swift 的預處理器 Preprocessor 可以讓我們在程式被編譯之前,做一些預先的處理。
其他語言的預處理器
預處理器的概念並不是 Swift 所獨有的,在 C 語言裡,就已經有預處理器了。
比如用來定義常數的 #define
:
#define PI 3.14159
或是用來納入 Library 的 #include
:
#include <stdio.h>
相信這兩個大家都不陌生,而它們就是所謂的「預處理器 Preprocessor」。
Swift 的預處理器
在 Swift 中的預處理器也會以「#」井字號開頭,而最常見的大概就是 #if
了。我們可以在編譯程式前先做一些處理,或是做一些判斷,來決定要執行什麼樣的程式,因為有些判斷值並不是我們可以在程式裡拿到的,比如最簡單的例子就是 OS,我們的 App 是跑在 iOS 上還是 macOS 上,在寫程式時我們並不知道。
Swift 語言中的 #if、#else、#elseif、#endif
我們可以用 #if 來判斷很多事情,以下整理並列出所有可以判斷的值:
判斷是否在 Debug 環境
DEBUG 是 Apple 預先幫我們建好的 Flag,我們可以用此來判斷是不是在 debug 的狀態,通常我們 build 在實機或是模擬機上都算是 debug 狀態,而如果是從 App Store 下載的話,就不是 debug 狀態。
#if DEBUG
// App 執行在測試環境
#else
// App 執行在正式版
#endif
我們可以在專案檔中的「Build Settings」→「All|Combined」→「Swift Compilers - Custom Flags」→「Active Compilation Conditions」裡看到 Apple 預先定好的 DEBUG Flag。
判斷程式執行在哪個作業系統上
#if os(iOS)
// 程式執行在 iOS 或 iPadOS 上
#elseif os(macOS)
// 程式執行在 macOS 上
#elseif os(tvOS)
// 程式執行在 tvOS 上
#elseif os(visionOS)
// 程式執行在 visionOS 上
#elseif os(watchOS)
// 程式執行在 watchOS 上
#elseif os(Linux)
// 程式執行在 Linux 上
#elseif os(Windows)
// 程式執行在 Windows 上
#elseif os(FreeBSD)
// 程式執行在 FreeBSD 上
#elseif os(Android)
// 程式執行在 Android 上
#elseif os(PS4)
// 程式執行在 PS4 上
#elseif os(Cygwin)
// 程式執行在 Cygwin 上
#elseif os(Haiku)
// 程式執行在 Haiku 上
#else
// 程式執行在未知的 OS 上,當 Apple 推出新的作業系統時,或 Swift 支援新的作業系統時,就會執行到這裡
#endif
除了 Apple 自己的作業系統,也能判斷別家的作業系統。而這裡比較特別的是,當我們寫 #if os(iOS)
時,會同時判斷到 iPadOS,且無法直接判斷 #if os(iPadOS)
。
判斷程式執行在哪種架構的處理器上
#if arch(powerpc64)
// 程式執行在 64-bit 的 PowerPC 處理器上
#elseif arch(powerpc64le)
// 程式執行在 64-bit 的 PowerPC Little Endian 處理器上
#elseif arch(s390x)
// 程式執行在 LinuxONE s390x 處理器上
#elseif arch(i386)
// 程式執行在 32-bit 的 Intel 處理器上
#elseif arch(x86_64)
// 程式執行在 64-bit 的 Intel 處理器上
#elseif arch(arm)
// 程式執行在 32-bit 的 ARM 處理器上
#elseif arch(arm64)
// 程式執行在 64-bit 的 ARM 處理器上
#else
// 程式執行在別的架構的處理器上
#endif
判斷可否納入某個框架
#if canImport(SwiftUI)
// 可 Import SwiftUI
#elseif canImport(Combine)
// 可 Import Combine
...
#else
...
#endif
判斷編譯器的版本
#if compiler(<4.2)
// 編譯器版本小於 4.2
#elseif compiler(>=5)
// 編譯器版本大於等於 5
#else
// 編譯器版本介於 4.2(含)和 5(不含)之間
#endif
判斷 App 執行的環境
#if targetEnvironment(macCatalyst)
// iOS App 執行在 macOS 上
#elseif targetEnvironment(simulator)
// App 執行在模擬機上
#else
// App 執行在實機上,且非 iOS App 執行在 macOS 上
#endif
判斷 Swift 的語言版本
#if swift(<4.2)
// Swift 語言的版本小於 4.2
#elseif swift(>=5)
// Swift 語言的版本大於等於 5
#else
// Swift 語言的版本介於 4.2(含)和 5(不含)之間
#endif
Swift 語言中的 #available、#unavailable
要判斷作業系統的話,我們要用 #if os() 來判斷,但如果是要更近一步的判斷作業系統的版本的話,就要使用 #available 和 #unavailable 了。
判斷是否滿足特定作業系統版本
if #available(iOS 17.2.1, *) {
// iOS 或 iPadOS 版本大於等於 17.2.1
// 或為 macOS、tvOS、visionOS、watchOS
}
在 #availabl 後方的 * 星號一定要寫,指的是包含其他所有沒提到的作業系統。我們也能一次判斷多個作業系統:
if #available(iOS 17.2.1, macOS 14.2.1, *) {
// iOS 或 iPadOS 版本大於等於 17.2.1,或 macOS 版本大於等於 14.2.1
// 或為 tvOS、visionOS、watchOS
}
判斷是否未達特定版本的作業系統
跟 #availabl 的邏輯相反,#unavailable 可以用來判斷是否作業系統未達特定的版本。
if #unavailable(iOS 17.2.1) {
// iOS 或 iPadOS 版本小於 17.2.1
}
在 #availabl 不一樣的地方是後方不用寫 * 星號。
關於 XcodeProject
XcodeProject 創立於 2023,致力於協助開發者探索 Apple 的創新世界,學習在 iOS、iPadOS、macOS、tvOS、visionOS 與 watchOS 上開發 App,發現眾多技術與框架,讓開發者獲得更多能力。