Prevent dismissal of UIAlertController

jona jürgen picture jona jürgen · Sep 2, 2014 · Viewed 21.4k times · Source

I am adding a UITextField to a UIAlertController, which appears as an AlertView. Before dismissing the UIAlertController, I want to validate the input of the UITextField. Based on the validation I want to dismiss the UIAlertController or not. But I have no clue how to prevent the dismissing action of the UIAlertController when a button is pressed. Has anyone solved this problem or any ideas where to start ? I went to google but no luck :/ Thanks!

Answer

matt picture matt · Sep 2, 2014

You're correct: if the user can tap a button in your alert, the alert will be dismissed. So you want to prevent the user from tapping the button! It's all just a matter of disabling your UIAlertAction buttons. If an alert action is disabled, the user can't tap it to dismiss.

To combine this with text field validation, use a text field delegate method or action method (configured in the text field's configuration handler when you create it) to enable/disable the UIAlertActions appropriately depending on what text has (or hasn't) been entered.

Here's an example. We created the text field like this:

alert.addTextFieldWithConfigurationHandler {
    (tf:UITextField!) in
    tf.addTarget(self, action: "textChanged:", forControlEvents: .EditingChanged)
}

We have a Cancel action and an OK action, and we brought the OK action into the world disabled:

(alert.actions[1] as UIAlertAction).enabled = false

Subsequently, the user can't tap OK unless there is some actual text in the text field:

func textChanged(sender:AnyObject) {
    let tf = sender as UITextField
    var resp : UIResponder = tf
    while !(resp is UIAlertController) { resp = resp.nextResponder() }
    let alert = resp as UIAlertController
    (alert.actions[1] as UIAlertAction).enabled = (tf.text != "")
}

EDIT Here's the current (Swift 3.0.1 and later) version of the above code:

alert.addTextField { tf in
    tf.addTarget(self, action: #selector(self.textChanged), for: .editingChanged)
}

and

alert.actions[1].isEnabled = false

and

@objc func textChanged(_ sender: Any) {
    let tf = sender as! UITextField
    var resp : UIResponder! = tf
    while !(resp is UIAlertController) { resp = resp.next }
    let alert = resp as! UIAlertController
    alert.actions[1].isEnabled = (tf.text != "")
}