iOS 開發 #10 Alert 與 Sheet 的開啟方式 (下) Alert

Han
彼得潘的 Swift iOS / Flutter App 開發教室
8 min readAug 10, 2024

前言

在上篇提到了 Sheet 的用法,這次來講講 Alert 的用法

Alert

在 App 中經常使用 AlertDialog 來提示、告知使用者必要的訊息

IBAction 中打入這段程式碼

let controller = UIAlertController(title: "標題", message: "訊息", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default)
controller.addAction(okAction)
present(controller, animated: true)

就能在按下按鈕後跳出 Alert 的視窗

  • title:設定 UIAlertController 的標題
  • message:設定 UIAlertController 要顯示的訊息
  • preferredStyle:設定 UIAlertController 的模式。他有兩種 .alert.actionSheet 可以選
  • addAction:設定 UIAlertController 的按鈕
  • present:設定欲顯示的 UIAlertController 與是否要有動畫

下面兩張圖是 preferredStyle: .alertpreferredStyle: .actionSheet 這兩個模式顯示的視窗

preferredStyle: .alert 會長這樣
preferredStyle: .actionSheet 會長這樣

上面提到的 titlemessagepresent 應該都沒什麼問題,看到名字後就能猜到他是什麼意思,addAction 雖然看得出是什麼,但 addAction 要什麼設定這應該是剛接觸 Alert 時會遇到的問題

首先 addAction 他接受一個 UIAlertAction 的物件

所以我們可以建立一個 UIAlertAction 的物件

他需要三個參數:titlestyle 以及 handler

  • title :設定按鈕顯示的內容
  • style :設定按鈕的風格。有 .default.cancel.destructive 三種
  • handler :設定按鈕按下所要做的事

呼叫多次的 addAction 可以加入多個按鈕

上面有提到 handler 可以新增按鈕的點擊事件,那要怎麼做呢?

把要做的事情加在 UIAlertAction 後面就好了

例如:

let okAction = UIAlertAction(title: "OK", style: .destructive) { _ in
print("OK")
}

這樣在按下 Alert 的按鈕後就會 print 出 OK

如果在 UIAlertAction 後面加上 {} 時會發現跳出錯誤了

不用緊張,這是代表你少打了一些東西,下面請我最好的工作夥伴 ChatGPT 來解釋一下關於 UIAlertAction

這個錯誤訊息 Contextual type for closure argument list expects 1 argument, which cannot be implicitly ignored 是因為在 UIAlertAction 的閉包中,系統預期你需要處理一個參數,但你在定義閉包時,沒有明確地接收這個參數

UIAlertAction 是什麼

UIAlertAction 是 iOS 中用來在 UIAlertController(一個彈出視窗)中添加按鈕選項的類別。每個 UIAlertAction 代表一個按鈕,當按鈕被點擊時,會執行與該按鈕相關聯的動作。這個動作通常以閉包的形式提供,閉包允許在按鈕被點擊後執行一段自定義的程式碼

為什麼需要使用閉包

閉包是一段自包含的功能代碼,可以在你的應用程式中傳遞和使用。當你在建立 UIAlertAction 時,你可以使用閉包來定義在按下按鈕時所要執行的程式碼邏輯

錯誤的原因

當你創建一個 UIAlertAction,其閉包函數預期會接收一個參數,這個參數是 UIAlertAction 本身。然而,你的閉包沒有接收這個參數,這導致了編譯器不滿意的錯誤

let okAction = UIAlertAction(title: "OK", style: .destructive) { action in
print("OK")
}

在上面的 Code 中,action 是一個 UIAlertAction 類型的參數,表示按下的這個按鈕。雖然你可能不使用這個參數,但你仍然需要明確地接收它。這樣就可以避免編譯器的錯誤

可忽略的情況

如果你確定不需要使用這個參數,可以用 _ 來忽略它:

let okAction = UIAlertAction(title: "OK", style: .destructive) { _ in
print("OK")
}

上面講的 UIAlertAction 是按鈕,那 UIAlertController 可以加上 Text Field 嗎?

當然可以,這就需要用到 .addTextField 來新增 Text Field

let controller = UIAlertController(title: "標題", message: "訊息", preferredStyle: .alert)
controller.addTextField { textField in
textField.placeholder = "Hint"
}
let okAction = UIAlertAction(title: "OK", style: .default) { _ in
let text = controller.textFields?[0].text
print(text ?? "")
}
controller.addAction(okAction)
present(controller, animated: false)

可以看到程式碼中新增一段

controller.addTextField { textField in
textField.placeholder = "Hint"
}

就是透過 addTextField 來把 Text Field 加入到 Alert

那因為 addTextField 也是閉包,所以也接收一個參數,而我這邊把這個參數叫做 textField 是因為我要調整 textFieldplaceholder 讓這個 Text Field 裡面有一個提示供使用者知道要輸入什麼東西

那要怎麼取資料呢?

這時需要到 action 裡面用 controller.textFields?[0].text 來取值,這邊用 [0] 是因為我只有一個 Text Field ,還有在上面的 Code 中,我的 print(text ?? "") 這邊好像怪怪的,其實這段是表示當 controller.textFields?[0].text 取到值時會讓 text = controller.textFields?[0].text ,而沒取到值時會讓 text = "" ,這樣能確保 text 裡面會有字串,即便是空字串也不會因為沒取到值讓 text = nil 使程式閃退

對於 Alert 其他用法有興趣,可以參考一下這篇文章

結論

這篇介紹了 UIAlertAction 模式與使用方法,透過上篇的 Sheet跟這篇的 Alert 就可以讓使用者使用 APP 時有一個良好的體驗

--

--