Search code examples
swiftuialertcontroller

Prevent dismissal of UIAlertController


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!


Solution

  • 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 != "")
    }