和 if let 很像的 guard let
guard 什麼都學 if,所以自然的,它也有個跟 optional binding 的 if let 很像的 guard let,專門判斷 optional 是否有值和讀取它的內容。
ps: 還不認識 guard 的朋友,可先參考以下連結的說明:
guard let 的基本語法
- 寫法 1
func showName(name: String?) {
guard let name else { return }
print("my name is \(name)")
}
- 寫法 2
func showName(name: String?) {
guard let name = name else { return }
print("my name is \(name)")
}
輸入 guard let 時,我們也可從 Xcode 的選單選擇 guardlet,讓它幫我們自動填入 guard let else 的基本格式。
值得注意的,如果 else { } 裡只要單純地 return,沒有要做其它事情,我們習慣將它寫在同一行,讓程式看起來更精簡。
guard let name else { return }
guard let 和 if let 的作用大同小異,同樣可讓 let 後的常數名和 optional 同名,主要的差別在以下幾個地方:
- guard let 的 else { } 程式將在 optional 無值時執行,跟 if let 相反,if let 的 { } 程式將在 optional 有值時執行。
- guard let 後的常數可在 guard let else { } 後繼續使用,if let 後的常數只能在 if let 的 { } 裡使用。
name 可在 guard let { } 後繼續使用,因此 \( ) 裡的 name 型別是 String。
func showName(name: String?) {
guard let name else { return }
print("my name is \(name)")
}
以下程式 \( ) 裡的 name 是 showName 的參數 name,不是 if let 後的 name,因此它的型別是 String?。
func showName(name: String?) {
if let name {
}
print("my name is \(name)")
}
- guard let { } 的程式必須離開原本 guard let 所在區塊,實現提早離開(early exit)的效果,因此 else 裡必須加入 return,break,continue 或 throw。
guard let 搭配 App 的表單輸入頁面
App 的表單輸入頁面很適合搭配 guard let 檢查欄位。比方我們做了一個通訊錄 App, 在新增聯絡人時,程式須做許多檢查,假設新增聯絡人的欄位有十個,我們可用十個 guard let 檢查是否每個欄位都有值,一旦某個 guard let 出錯即顯示錯誤,不再往下執行。唯有通過十個 guard let 的層層考驗,才會執行最後新增聯絡人的動作。
跟 if let 一樣,guard let 也可以串接多個 optional,因此檢查表單欄位新增資料的例子,將可寫成以下的 createBook function。
func createBook(title: String?, price: Double?, pages: Int?) {
guard let title,
let price,
let pages else { return }
// 以下區塊可加入新增 Book 的程式碼
print("\(title) costs $\(price) and has \(pages) pages.")
}
createBook(title: "彼得潘的 Swift 程式設計入門", price: 99999, pages: 1000)
比起原本 if let 的寫法,guard let 看起來可讀性更佳,因為它少了一層縮排,而且更清楚表達建立資料的相關程式在 else { } 之後。
func createBook(title: String?, price: Double?, pages: Int?) {
if let title,
let price,
let pages {
// 以下區塊可加入新增 Book 的程式碼
print("\(title) costs $\(price) and has \(pages) pages.")
}
}
跟 if let 一樣,當我們利用 guard let 讀出 optional 的內容後,還可以針對內容做判斷,例如以下例子判斷金額超過 1000 的書才是好書。
func createBook(title: String?, price: Double?, pages: Int?) {
guard let title,
let price,
let pages,
price > 1000 else { return }
// 以下區塊可加入新增 Book 的程式碼
print("\(title) costs $\(price) and has \(pages) pages.")
print("It is a good book!")
}
createBook(title: "彼得潘的 Swift 程式設計入門", price: 99999, pages: 1000)
開發 iOS App 時使用 guard let 的例子
利用 guard let 得到 cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "LoverTableViewCell", for: indexPath) as? LoverTableViewCell else { return UITableViewCell() }
let lover = lovers[indexPath.row]
cell.nameLabel.text = lover.name
cell.photoImageView.image = UIImage(named: lover.imageName)
return cell
}
在 prepare 裡利用 guard let 檢查是否可以傳資料
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let loverDetailViewController = segue.destination as? LoverDetailViewController,
let row = tableView.indexPathForSelectedRow?.row else { return }
loverDetailViewController.lover = lovers[row]
}