Swift

2023 年 10 月 4 日

Swift 語言的預處理器 Preprocessor

已複製到剪貼板


Swift 的預處理器 Preprocessor 可以讓我們在程式被編譯之前,做一些預先的處理。

Swift Statements

其他語言的預處理器

預處理器的概念並不是 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。

Swift Compilers-Custom Flags:DEBUG

判斷程式執行在哪個作業系統上

#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 不一樣的地方是後方不用寫 * 星號。

分享文章

已複製到剪貼板

主題文章

查看 Swift

超級感謝

關於 XcodeProject

XcodeProject 創立於 2023,致力於協助開發者探索 Apple 的創新世界,學習在 iOS、iPadOS、macOS、tvOS、visionOS 與 watchOS 上開發 App,發現眾多技術與框架,讓開發者獲得更多能力。


Contacts

Ricky Chuang

XcodeProject

RickyChuang.xcodeproj@gmail.com

XcodeProject 聯絡

contact.xcodeproj@gmail.com

最新文章