你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> UIAlertController

UIAlertController

編輯:IOS開發基礎

你知道 UIAlertView、UIActionSheet (以及它們各自的 delegate protocols) 在 iOS 8 中已經被廢棄了嗎?

這是真的。在你的代碼中按住QQ圖片20141219102558.png點擊 UIAlertView 或者 UIActionSheet,你就會看到最上面的注釋:

UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead.

你可能好奇為什麼 Xcode 不直接警告你這個變化呢?別急,往下讀:

@availability(iOS, introduced=2.0)

雖然類已經被廢棄了,但在 @availability 屬性中並沒有表達出這一點。UIAlertView 目前還是能用的。

最開始的時候,UIAlertView 充滿了無底線的讓步,犧牲格式和設計正確性來順應開發者的喜好。它的 delegate 類型是在初始化函數中注釋的 (delegate:(id /*

UIActionSheet 也一樣糟糕,但是開發者大多數時間裡都沒時間想起那些糟糕的使用方法,與其相關的抱怨特就更少了。

因此,介紹 UIAlertController 給大家,就好比派出軍隊解放一座被占領的城市一樣。它不僅僅改進了那些讓人頭疼的 API,也開辟了一條為最新設備上 UIKit 特性適配的新路徑。

本文章的主題就是 UIAlertController,向大家展示如何替換舊的 alert,以及這些操作方法的高級擴展。


UIAlertController 同時替代了 UIAlertView 和 UIActionSheet,從系統層級上統一了 alert 的概念 —— 即以 modal 方式或 popover 方式展示。

UIAlertController 是 UIViewController 的子類,而非其先前的方式。因此新的 alert 可以由 view controller 展示相關的配置中獲益很多。

UIAlertController 不管是要用 alert 還是 action sheet 方式展示,都要以 title 和 message 參數來初始化。Alert 會在當前顯示的 view controller 中心以模態形式出現,action sheet 則會在底部滑出。Alert 可以同時有按鈕和輸入框,action sheet 僅支持按鈕。

新的方式並沒有把所有的 alert 按鈕配置都放在初始化函數中,而是引入了一個新類 UIAlertAction 的對象,在初始化之後可以進行配置。這種形式的 API 重構讓對按鈕數量、類型、順序方便有了更大的控制。同時也棄用了 UIAlertView 和 UIActionSheet 使用的delegate 這種方式,而是采用更簡便的完成時回調。

新舊 Alert 方式對比

標准的 Alert 樣式

uialertcontroller-alert-defautl-style.png

舊方法:UIAlertView

let alertView = UIAlertView(title: "Default Style", message: "A standard alert.", delegate: self, cancelButtonTitle: "Cancel", otherButtonTitles: "OK")
alertView.alertViewStyle = .Default
alertView.show()
// MARK: UIAlertViewDelegate
func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) {
    switch buttonIndex {
        // ...
    }
}

新方法:UIAlertController

let alertController = UIAlertController(title: "Default Style", message: "A standard alert.", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
    // ...
}
alertController.addAction(cancelAction)
let OKAction = UIAlertAction(title: "OK", style: .Default) { (action) in
    // ...
}
alertController.addAction(OKAction)
self.presentViewController(alertController, animated: true) {
    // ...
}

標准的 Action Sheet 樣式

uialertcontroller-action-sheet-automatic-style.png

UIActionSheet

let actionSheet = UIActionSheet(title: "Takes the appearance of the bottom bar if specified; otherwise, same as UIActionSheetStyleDefault.", delegate: self, cancelButtonTitle: "Cancel", destructiveButtonTitle: "Destroy", otherButtonTitles: "OK")
actionSheet.actionSheetStyle = .Default
actionSheet.showInView(self.view)
// MARK: UIActionSheetDelegate
func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) {
    switch buttonIndex {
        ...
    }
}

UIAlertController

let alertController = UIAlertController(title: nil, message: "Takes the appearance of the bottom bar if specified; otherwise, same as UIActionSheetStyleDefault.", preferredStyle: .ActionSheet)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
    // ...
}
alertController.addAction(cancelAction)
let OKAction = UIAlertAction(title: "OK", style: .Default) { (action) in
    // ...
}
alertController.addAction(OKAction)
let destroyAction = UIAlertAction(title: "Destroy", style: .Destructive) { (action) in
    println(action)
}
alertController.addAction(destroyAction)
self.presentViewController(alertController, animated: true) {
    // ...
}

新功能

UIAlertController 並不只是對已有的 API 做了清理,而是進行了標准化歸納。以前,預設的樣式閒置有很多(swizzling 雖然可以提供更多的功能但還是有很大風險)。UIAlertController 讓以前看起來很神奇的事情變為了可能。

UIAlertController is not just a cleanup of pre-existing APIs, it's a generalization of them. Previously, one was constrained to whatever presets were provided (swizzling in additional functionality at their own risk). With UIAlertController, it's possible to do a lot more out-of-the-box:

帶有警示按鈕的 Alert

uialertcontroller-alert-cancel-destroy.png

這種行為已經被 UIAlertActionStyle 所涵蓋,共有三種類型:

.Default: 對按鈕應用標准樣式。

.Cancel: 對按鈕應用取消樣式,代表取消操作不做任何改變。

.Destructive: 對按鈕應用警示性的樣式,提示用戶這樣做可能會改變或刪除某些數據。

所以想要對模態的 alert 加一個警示性的按鈕,只需要加上 .Destructive 風格的 UIAlertAction 屬性:

let alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .Alert)
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (action) in
    println(action)
}
alertController.addAction(cancelAction)
let destroyAction = UIAlertAction(title: "Destroy", style: .Destructive) { (action) in
    println(action)
}
alertController.addAction(destroyAction)
self.presentViewController(alertController, animated: true) {
    // ...
}

大於 2 個按鈕的 Alert

uialertcontroller-alert-one-two-three-cancel.png

有 1 個或者 2 個操作的時候,按鈕會水平排布。更多按鈕的情況,就會像 action sheet 那樣展示:

let oneAction = UIAlertAction(title: "One", style: .Default) { (_) in }
let twoAction = UIAlertAction(title: "Two", style: .Default) { (_) in }
let threeAction = UIAlertAction(title: "Three", style: .Default) { (_) in }
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (_) in }
alertController.addAction(oneAction)
alertController.addAction(twoAction)
alertController.addAction(threeAction)
alertController.addAction(cancelAction)

創建登錄表單

uialertcontroller-alert-username-password-login-forgot-password-cancel.png

iOS 5 就為 UIAlertView 加入了 alertViewStyle 屬性,將原本私有的 API 暴露出來給開發者使用 —— 像某些系統內建應用一樣允許在 alert 中顯示登錄和密碼框。

在 iOS 8 中,UIAlertController 則加入了 addTextFieldWithConfigurationHandler 方法:

let loginAction = UIAlertAction(title: "Login", style: .Default) { (_) in
    let loginTextField = alertController.textFields![0] as UITextField
    let passwordTextField = alertController.textFields![1] as UITextField
    login(loginTextField.text, passwordTextField.text)
}
loginAction.enabled = false
let forgotPasswordAction = UIAlertAction(title: "Forgot Password", style: .Destructive) { (_) in }
let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel) { (_) in }
alertController.addTextFieldWithConfigurationHandler { (textField) in
    textField.placeholder = "Login"
    NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object: textField, queue: NSOperationQueue.mainQueue()) { (notification) in
        loginAction.enabled = textField.text != ""
    }
}
alertController.addTextFieldWithConfigurationHandler { (textField) in
    textField.placeholder = "Password"
    textField.secureTextEntry = true
}
alertController.addAction(loginAction)
alertController.addAction(forgotPasswordAction)
alertController.addAction(cancelAction)

創建注冊表單

uialertcontroller-alert-sign-up.png

UIAlertController 想得比以前更周到一些,它提供了展示無限個輸入框的權限,並且每一個輸入框都可以根據需求進行自定義。這讓僅在一個模態的 alert 中實現完善的注冊功能成為可能:

alertController.addTextFieldWithConfigurationHandler { (textField) in
    textField.placeholder = "Email"
    textField.keyboardType = .EmailAddress
}
alertController.addTextFieldWithConfigurationHandler { (textField) in
    textField.placeholder = "Password"
    textField.secureTextEntry = true
}
alertController.addTextFieldWithConfigurationHandler { (textField) in
    textField.placeholder = "Password Confirmation"
    textField.secureTextEntry = true
}

雖然有了這些,但必須要說明的是,不用矯枉過正。不能因為你可以這樣做,就代表你應該這樣做。忘了這玩意吧,提供一個 view controller 來做注冊功能吧,因為你本就應該這樣做!

注意

如果試圖向 alert controller 添加帶有 .ActionSheet 屬性的輸入框,將會拋出異常:

Terminating app due to uncaught exception NSInternalInconsistencyException, reason: 'Text fields can only be added to an alert controller of style UIAlertControllerStyleAlert'

同樣的,向 alert 或 action sheet 添加一個以上的 .Cancel 按鈕將會拋出異常:

Terminating app due to uncaught exception NSInternalInconsistencyException, reason: 'UIAlertController can only have one action with a style of UIAlertActionStyleCancel'

(文章由Croath Liu翻譯自NShipster)

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved