Swift 與 Objective-C

Swift Optional:區分 nil、空字串與零

用六種輸入保留缺值與無效狀態,實測nil合併運算子的預設值何時執行,避免把數字0誤當成沒有輸入。

閱讀 2 分鐘
Swift Optional:區分 nil、空字串與零 封面圖

nil、空字串與數字0是不同狀態。把所有可選值都換成預設值,可能抹掉未輸入與明確輸入0的差別。先決定缺值應採用正常預設值,還是保留為獨立狀態。

原理與設計判斷

Optional用some與none表示存在與否。局部條件處理選if let,提前返回選guard let,有合理預設值時選??。可選鏈結遇到缺值會得到nil;強制解包在nil時中止,不適合預期中的輸入失敗。 第一手資料

重現程式碼

quantity用不同enum表示缺值、無效與有效數量。六個案例是nil、空字串、cat、-1、0、7。預設值函式記錄??呼叫次數,並另外比較空字串與缺值字串的count。

這個獨立範例已於 2026-10-23 使用 Apple Swift 6.4,以 Swift 6 語言模式在 arm64 macOS 目標環境執行。不需要網路或額外套件。

下載完整 Swift 檔案

請在下載檔案的資料夾執行。檢查不符時,precondition 會中止程式。請勿使用 -Ounchecked,因為它會移除這些檢查。

swift -swift-version 6 swift-optional-enum-unwrapping.swift
enum Quantity: Equatable { case missing, invalid, value(Int) }
func quantity(_ raw: String?) -> Quantity {
    guard let raw else { return .missing }
    guard let value = Int(raw), value >= 0 else { return .invalid }
    return .value(value)
}

let cases: [(String?, Quantity)] = [
    (nil, .missing), ("", .invalid), ("cat", .invalid),
    ("-1", .invalid), ("0", .value(0)), ("7", .value(7))
]
for (raw, expected) in cases { precondition(quantity(raw) == expected) }

var fallbackCalls = 0
@MainActor func fallback() -> Int { fallbackCalls += 1; return 99 }
let present: Int? = 0
let absent: Int? = nil
precondition((present ?? fallback()) == 0 && fallbackCalls == 0)
precondition((absent ?? fallback()) == 99 && fallbackCalls == 1)

let empty: String? = ""
let missing: String? = nil
precondition(empty?.count == 0 && missing?.count == nil)
print("inputs=6 missing=1 invalid=3 valid=2 fallback-calls=1 empty-count=0 missing-count=nil")

執行結果與解讀

inputs=6 missing=1 invalid=3 valid=2 fallback-calls=1 empty-count=0 missing-count=nil

結果區分出一個缺值、三個無效輸入與兩個有效值。some(0)不執行預設值函式,none才執行一次。空字串的count是0,缺值字串的鏈結結果則是nil。類似零的值不代表不存在。

適用範圍與限制

這是拒絕負數的數量驗證器,不是通用數字輸入政策。空白、小數、地區格式與上限都需依需求補上。String!也是會在需要的情境下隱含解包的可選宣告,不是每次使用都無條件強制解包。

接下來要確認的事

先決定缺值與無效輸入是否顯示不同提示,並與伺服器契約一致。如果呼叫端需要更細的失敗原因,請透過throws或Result保留資訊,而不是默默覆蓋成預設值。

延伸實驗

來源與驗證