0

I've created a UIAlertController with a text field and an action to send a verification code to the user's phone number. However, the action dismisses the alert controller as well, making the user unable to enter the verification code. Is there a way to make an alert action not dismiss the alert controller?

   let alertController = UIAlertController(title: "Verification", message: "a code has been sent to your phone number", preferredStyle: .alert)

let confirm = UIAlertAction(title: "Confirm", style: .default, handler: {
    alert -> Void in
    //verifies code
})

let resend = UIAlertAction(title: "Resend", style: .default, handler: {
        alert -> Void in
        //resends code
    })

let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: {
    (action : UIAlertAction!) -> Void in

})

alertController.addTextField { (textField : UITextField!) -> Void in
    textField.placeholder = "Enter code"
}

alertController.addAction(confirm)
alertController.addAction(resend)
alertController.addAction(cancelAction)

self.present(alertController, animated: true, completion: nil)
Pirlo Lochisomo
  • 185
  • 1
  • 16

3 Answers3

0

You can use the UITextFieldDelegate and isEnabled property of UIAlertAction to achieve the desired effect.

Steps:

  1. Your class should confirm to UITextFieldDelegate
  2. Your alert's action should be declared as a class level property
  3. Disabled the alert action before displaying the alert
  4. Configure the textfield and set delegate as your class
  5. Implement shouldChangeCharactersIn: method
  6. If text length is greater than desired length enable the alert action, else disable the alert action

Code:

// Your Class should confirm to UITextFieldDelegate
class ViewController: UIViewController, UITextFieldDelegate
{
    // Verify alert action, alert button that want to be disabled
    var verifyAction : UIAlertAction!

    // Shows the alert
    @IBAction func showAlert(sender : UIButton)
    {
        let alert    = UIAlertController(title: "Verify", message: "Please Enter the verification code to continue", preferredStyle: UIAlertControllerStyle.alert)
        verifyAction = UIAlertAction(title: "Verify", style: UIAlertActionStyle.default) { (action) in
            // Do verification and other stuffs
        }

        // Configures textfield properties and delegate
        alert.addTextField { (textField) in
            textField.placeholder = "Verification Code"
            textField.delegate    = self
        }

        // Disables the button
        verifyAction.isEnabled = false
        alert.addAction(verifyAction)
        self.present(alert, animated: true, completion: nil)
    }

    // Textfield delegate method for observing the text change
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
    {
        // if text length is greater than 0 enables the button, else disables it
        let existingText = textField.text as NSString?
        if let replacedText = existingText?.replacingCharacters(in: range, with: string), replacedText.characters.count > 0
        {
            verifyAction.isEnabled = true
        }
        else
        {
            verifyAction.isEnabled = false
        }
        return true
    }
}

Note: I wrote this answer before you posting the code, so it was not based on the code you provided with your question. It's a generic answer, I'll edit the answer if you want me to do so.

Midhun MP
  • 103,496
  • 31
  • 153
  • 200
0

By using the default alert controller, on tapping any of the alert action button will dismiss the alert controller. You may have to create your own custom view/viewcontroller and perform the corresponding action or use some third party libraries.

Aravind A R
  • 2,674
  • 1
  • 15
  • 25
0

Try this Code, because this works fine to me :

func createAlert() {
    // initializing
    let alertControler = UIAlertController(title: "Your Title",
                                           message: "Your message",
                                           preferredStyle: .Alert)
    // create actions
    let confirmAction = UIAlertAction(title: "Confirm", style: .Default, handler: {
        (action) -> Void in self.confirmAction()
    })

    let resendAction = UIAlertAction(title: "Resend", style: .Default, handler: {
        (action) -> Void in self.resendAction()
    })

    let cancelAction = UIAlertAction(title: "Cancel", style: .Default, handler: {
        (action) -> Void in self.dismissAlert()
    })

    // add actions
    alertControler.addAction(confirmAction)
    alertControler.addAction(resendAction)
    alertControler.addAction(cancelAction)

    self.presentViewController(alertControler, animated: true, completion: nil)
}

// initiate this func to your class
@objc private func dismissAlert() {
    self.dismissViewControllerAnimated(true, completion: nil)
}

@objc private func confirmAction() {
    // yuor action here
}

@objc private func resendAction() {
    // your action here
}

And just implement self.createAlert() to your main action. Or implement "self.dismissViewControllerAnimated(true, completion: nil)" to your cancelAction

rijeqi rahma
  • 73
  • 1
  • 4