Swift Optional? | Swift 基礎篇 Optional?

黃士軒
黃士軒
Jul 28, 2017 · 6 min read
CC 3.0 by vaadin

在介紹 Swift 的功能特點之前,先讓大家看看在 Swift 中,如何用一行程式碼實作出大家最熟悉的「Hello, world」

println("Hello, world")

在 Swift 中,這行程式碼就是一個完整的程式,你會發現兩個 Swift 特點

  1. 不需要 main 函式,在全域作用域中的程式碼會被自動當做程式的入口點
  2. 不需要在每一行程式碼句尾寫上分號

這兩點看似沒什麼大不了,但是對之後實作iOS APP的時候,就會發現此Coding Style的妙處。而接下來,我將開始介紹Swift中最常看到的型態 — Optional


var y: Int? = nil
var z: Int? = 20

作為一個Swift的新手,一開始看到上面兩行程式碼一定會一頭霧水,
var y: Int = 20 不難理解,但是多了一個?nil到底是什麼?

其實這是一個Swift所創的新型別,稱作 Optional(可選型別)。把 Optional 想像成一個”包裝”,在這個包裝裡面有兩種可能

  1. 有放物品,像是 String 或是 Int
  2. 包空氣 (nil)

這樣說可能還是很抽象,讓我再用另外一種方式翻譯翻譯。
但是在介紹之前,我必須先提出另外一個 Swift 的功能 enum, 有接觸過C語言的話,對 enum 這個名詞其實不陌生,只是在 Swift 中,透過 Closure 的概念讓 enum 博大精深化(之後會再介紹)。而這裡我們就先用簡單的 enum 來為大家解開 Optional 的秘密

enum Optional<T> {
case Some(T)
case none
}

因為 Optional 代表”有”或”無”,所以 enum的宣告為兩個型態:

  1. some(T),代表有東西。而T為要傳入東西的型態,這是 Associate Value
    (相關值)的概念,代表當Optional為Some的型態,就把要放的東西放在T中
  2. 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 的觀念之後,那又該如何把包裝打開,拿出我們想要的值呢?

var x: String? = "Hello"
print(x)

// Output
Optional("Hello")

相信你會立刻想到上面的方法,然而你會發現 Output 結果會是Optional(…),因為沒有把 Optional 解開,系統就會把它看成一個 Optional的變數。所以以下介紹3種解開 Optional 的方法

// 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就不是個好的體驗,所以在使用!時必須多加注意。

// 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的方式

var x: String? = nil
let y = x ?? "Error!!!"
print(y)

// Output
Error!!!

這是縮寫的用法,透過??化簡 if...let 的判斷,讓程式碼看起來較為清晰簡略


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.

TheHenrysTime

Geeks, Life, Gadget Sharing

黃士軒

Written by

黃士軒

S.H.I.H

TheHenrysTime

Geeks, Life, Gadget Sharing

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade