顯示警告訊息和選單的 UIAlertController

使用 iOS App 時,我們時常看到兩種視窗。

一種是從中間彈出的訊息視窗,告訴我們特別的錯誤訊息或是徵求我們同意某種權限。

另一種則是由下而上彈出的選單視窗,提供一些可點選的選項。

不管是從中間彈出的訊息還是由下而上彈出的選單,都可以透過 UIAlertController 實現。接下來我們就來看看 UIAlertController 的各種應用,包含 alert & actionSheet 兩種樣式,以及如何增添輸入文字的 text field。

顯示從中間彈出的錯誤訊息。

if girlFriendTextField.text?.isEmpty == true {
let controller = UIAlertController(title: "怎麼可以忘了!", message: "忘了輸入女朋友的名字", preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK", style: .default)
controller.addAction(okAction)
present(controller, animated: true)
}

說明

let controller = UIAlertController(title: "怎麼可以忘了!", message: "忘了輸入女朋友的名字", preferredStyle: .alert)

參數 preferredStyle 傳入 .alert 將顯示從中間彈出的視窗。

let okAction = UIAlertAction(title: "OK", style: .default)

利用 UIAlertAction 生成視窗上顯示的按鈕。我們至少要提供一個按紐,到時候才能點選按紐關掉視窗。

參數 style 控制文字的樣式顏色,.destructive 是紅色,.default 和 .cancel 是藍色,設定 UIAlertController 的 view.tintColor 可調整 .default 和 .cancel 的顏色。

controller.addAction(okAction)

利用 addAction 加入按鈕。呼叫多次 addAction 可加入多個按鈕。

詢問是否同意做某件事。

顯示多個按鈕,並設定點選按鈕時做的事情。

let controller = UIAlertController(title: "工具人提醒", message: "是否每天晚上九點提醒送宵夜 ?", preferredStyle: .alert)
let okAction = UIAlertAction(title: "好的", style: .default) { _ in
print("在行事曆裡加入送宵夜的提醒")
}
controller.addAction(okAction)
let cancelAction = UIAlertAction(title: "取消", style: .cancel)
controller.addAction(cancelAction)
present(controller, animated: true)

說明

let okAction = UIAlertAction(title: "好的", style: .default) { _ in
print("在行事曆裡加入送宵夜的提醒")
}

利用 UIAlertAction 的第三個參數 handler 傳入的 closure 控制點選按鈕要做的事情。

按鈕的排列方向和順序

  • 2 個按鈕時左右排列,排列的順序依據 addAction 的順序,若有 cancel 樣式的按鈕則固定在左邊。
  • 超過 2 個時上下排列,按鈕的數量沒有限制,數量太多時會變成上下捲動,排列的順序依據 addAction 的順序,若有 cancel 樣式的按鈕將排在最後一個。

在彈出視窗裡顯示文字輸入框。

let controller = UIAlertController(title: "登入", message: "請輸入你在 B12 星球的電話和密碼", preferredStyle: .alert)
controller.addTextField { textField in
textField.placeholder = "電話"
textField.keyboardType = UIKeyboardType.phonePad
}
controller.addTextField { textField in
textField.placeholder = "密碼"
textField.isSecureTextEntry = true
}
let okAction = UIAlertAction(title: "OK", style: .default) { [unowned controller] _ in
let phone = controller.textFields?[0].text
let password = controller.textFields?[1].text
print(phone, password)
}
controller.addAction(okAction)
let cancelAction = UIAlertAction(title: "取消", style: .cancel)
controller.addAction(cancelAction)
present(controller, animated: true)

說明

controller.addTextField { textField in
textField.placeholder = "電話"
textField.keyboardType = UIKeyboardType.phonePad
}

利用 addTextField 加入 text field,從參數 configurationHandler 傳入的 closure 設定 text field 的樣式。

func addTextField(configurationHandler: ((UITextField) -> Void)? = nil)
let okAction = UIAlertAction(title: "OK", style: .default) { [unowned controller] _ in
let phone = controller.textFields?[0].text
let password = controller.textFields?[1].text
print(phone, password)
}

從 UIAlertController 的 textFields 讀取 text filed 的內容。值得注意的,我們必須加上 capture list [unowned controller],避免 reference cycle 造成的記憶體問題。

由下而上彈出的選單視窗。

let controller = UIAlertController(title: "真心話大冒險", message: "請問誰是你的最愛?", preferredStyle: .actionSheet)
let names = ["小龍女", "中龍女", "大龍女"]
for name in names {
let action = UIAlertAction(title: name, style: .default) { action in
print(action.title)
}
controller.addAction(action)
}
let cancelAction = UIAlertAction(title: "取消", style: .cancel)
controller.addAction(cancelAction)
present(controller, animated: true)

說明

let controller = UIAlertController(title: "真心話大冒險", message: "請問誰是你的最愛?", preferredStyle: .actionSheet)

參數 preferredStyle 傳入 .actionSheet 將顯示由下而上彈出的選單視窗。

for name in names {
let action = UIAlertAction(title: name, style: .default) { action in
print(action.title)
}
controller.addAction(action)
}

選項的數量由 UIAlertAction 控制,加入愈多 UIAlertAction 就可以有愈多選項。如果加入太多選項畫面會不會塞不下呢 ? 別擔心,當選項太多時,UIAlertController 會自動變身成可以上下捲動的選單呢。

在生成 UIAlertAction 時,我們可由參數 handler 傳入的 closure 得知使用者點選的選項。因為 closure 裡包含 UIAlertAction 物件,因此我們可由它的 title 知道使用者點選的標題。

convenience init(title: String?, 
style: UIAlertAction.Style,
handler: ((UIAlertAction) -> Void)? = nil)
let cancelAction = UIAlertAction(title: "取消", style: .cancel, handler: nil)

樣式 .cancel 的 UIAlertAction 將變成選單的最後一個選項,而且它是可憐的邊緣人,其它的選項不想靠近它,跟它之間有段小小的間隔。

值得注意的,在 iPad 顯示 action sheet 時必須設定彈出框顯示的位置,否則會造成 App 閃退,相關說明可參考以下連結。

顯示 alert 前檢查出問題的頁面是否正顯示著

取得 App 最後一個被 present 的 view controller

作品集

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com