Swift Optional? | Swift 基礎篇 Optional?

在介紹 Swift 的功能特點之前,先讓大家看看在 Swift 中,如何用一行程式碼實作出大家最熟悉的「Hello, world」
println("Hello, world")在 Swift 中,這行程式碼就是一個完整的程式,你會發現兩個 Swift 特點
- 不需要 main 函式,在全域作用域中的程式碼會被自動當做程式的入口點
- 不需要在每一行程式碼句尾寫上分號
這兩點看似沒什麼大不了,但是對之後實作iOS APP的時候,就會發現此Coding Style的妙處。而接下來,我將開始介紹Swift中最常看到的型態 — Optional
使用 Optional
var y: Int? = nil
var z: Int? = 20作為一個Swift的新手,一開始看到上面兩行程式碼一定會一頭霧水,var y: Int = 20 不難理解,但是多了一個?跟nil到底是什麼?
其實這是一個Swift所創的新型別,稱作 Optional(可選型別)。把 Optional 想像成一個”包裝”,在這個包裝裡面有兩種可能
- 有放物品,像是 String 或是 Int
- 包空氣 (nil)
這樣說可能還是很抽象,讓我再用另外一種方式翻譯翻譯。
但是在介紹之前,我必須先提出另外一個 Swift 的功能 enum, 有接觸過C語言的話,對 enum 這個名詞其實不陌生,只是在 Swift 中,透過 Closure 的概念讓 enum 博大精深化(之後會再介紹)。而這裡我們就先用簡單的 enum 來為大家解開 Optional 的秘密
enum Optional<T> {
case Some(T)
case none
}因為 Optional 代表”有”或”無”,所以 enum的宣告為兩個型態:
- some(T),代表有東西。而T為要傳入東西的型態,這是 Associate Value
(相關值)的概念,代表當Optional為Some的型態,就把要放的東西放在T中 - none,代表空值。當 Optional 為 none 的型態,就是 nil 的意思
所以我們就可以這樣來理解 Optional
let x: String? = “Hello Optional”
let x = Optional<String>.some(“Hello Optional”)
//上面兩行為等價
let x: String? = nil //如果不指定nil 預設也會是nil的狀態
let x = Optional<String>.none
//上面兩行為等價解開 Optional(Unwrapping)
認識了 Optional 的觀念之後,那又該如何把包裝打開,拿出我們想要的值呢?
var x: String? = "Hello"
print(x)
// Output
Optional("Hello")相信你會立刻想到上面的方法,然而你會發現 Output 結果會是Optional(…),因為沒有把 Optional 解開,系統就會把它看成一個 Optional的變數。所以以下介紹3種解開 Optional 的方法
#1 使用 ! 強制解開
// case 1
var x: String? = "Hello World"
let y: String = x!
print(y)
// case 2
var x: String? = nil
let y: String = x!
print(y)
// Output
Hello World
Error Message!這是最簡單直接的方法,把想要解開的Optional變數掛上!,就可以輕易拿到包裝裡的內容。然而如果是解開 nil 的Optioanl變數,就會造成 Error 發生。這在Debug階段是很好的工具,因為可以快速知道哪邊的程式有問題。不過如果再客戶使用時發生Error就不是個好的體驗,所以在使用!時必須多加注意。
#2 使用 if … let 先判斷在解開
// case 1
var x: String? = "Hello World"
if let y = x {
print(y)
}
// case 2
var x: String? = nil
if let y = x {
print(y)
}else{
Print("Error!!!")
}
// Output
Hello World
Error!!!透過 if…let 的方式,讓Optional變數在 nil 值的時候被解開也不會跳出error,而是執行else語句中的程式碼,提供一個安全解開Optional的方式
#3 使用 Nil Coalescing Operator (??)
var x: String? = nil
let y = x ?? "Error!!!"
print(y)
// Output
Error!!!這是縮寫的用法,透過??化簡 if...let 的判斷,讓程式碼看起來較為清晰簡略
補充 Optional Chaining
Optional Chaining 是在 Optional 裡面去解開包裝,所以就算中間有 nil,仍有一層 Optional 包住,就不會造成 Crash
if let 口味: String = things.餅乾包裝?.口味 {
// 當解開 Optional 時都沒有nil,就可以對口味字串進行處理
} else {
//如果 餅乾包裝 或 口味 是nil,就會執行此行
}如果再加上前面的??的用法,就可以縮減成一行來寫
if let 口味: String = things.餅乾包裝?.口味 ?? "Error!!!"如此一來,對於之後在處理多了 Optional 就方便多了
Optional 在 Swift 中佔有舉足輕重的角色,有了它真的讓開發變的更有彈性。像是在 ViewController 的 class 中,如果宣告一個 Int 變數必須先指定初始值,這時候就要呼叫 Init 函數進行設定,用 Int? 預設 nil,就不用設定 Init 函數。或是在進行不同 view 切換的時候(Segue), Optional 也會讓 Coding 變得安全方便許多。
Ref.

