¿Cómo valido TextFields en un UIAlertController?

¿Alguien puede decirme cómo validar UITextFields dentro de un UIAlertController ?

Lo necesito para evitar que el usuario click "Guardar" a less que se ingresen ambos campos.

Aquí está mi código hasta ahora:

 @IBAction func btnStart(sender: AnyObject) { var alert = UIAlertController(title: "New user", message: "Add a new user", prefernetworkingStyle: .Alert) let saveAction = UIAlertAction(title: "Save", style: .Default) { (action: UIAlertAction!) -> Void in self.textFieldName = alert.textFields![0] as UITextField self.textFieldEmail = alert.textFields![1] as UITextField self.saveUser(self.textFieldName.text, email: self.textFieldEmail.text) self.tableView.reloadData() } saveAction.enabled = false let cancelAction = UIAlertAction(title: "Cancel", style: .Default) { (action: UIAlertAction!) -> Void in } alert.addTextFieldWithConfigurationHandler { (textFieldName: UITextField!) in textFieldName.placeholder = "Enter full name" } alert.addTextFieldWithConfigurationHandler { (textFieldEmail: UITextField!) in textFieldEmail.placeholder = "Enter valid email adress" textFieldEmail.keyboardType = .EmailAddress } alert.addAction(saveAction) alert.addAction(cancelAction) presentViewController(alert, animated: true, completion: nil) } 

Esta es mi function para validar el campo Correo electrónico:

 func isValidEmail(testStr:String) -> Bool { let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}" if let emailTest = NSPnetworkingicate(format:"SELF MATCHES %@", emailRegEx) { return emailTest.evaluateWithObject(testStr) } return false } 

La forma más elegante es usar

 NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange... 

Ejemplo de Swift 3.0

 let alert = UIAlertController(title: nil, message: nil, prefernetworkingStyle: .alert) alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) let saveAction = UIAlertAction(title:"Save", style: .destructive, handler: { (action) -> Void in }) alert.addAction(saveAction) alert.addTextField(configurationHandler: { (textField) in textField.placeholder = "Enter something" NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextFieldTextDidChange, object: textField, queue: OperationQueue.main) { (notification) in saveAction.isEnabled = textField.text!.length > 0 } }) present(alert, animated: true, completion: nil) 

Esto se puede hacer al extender UIAlertViewController :

 extension UIAlertController { func isValidEmail(_ email: String) -> Bool { return email.characters.count > 0 && NSPnetworkingicate(format: "self matches %@", "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,64}").evaluate(with: email) } func isValidPassword(_ password: String) -> Bool { return password.characters.count > 4 && password.rangeOfCharacter(from: .whitespacesAndNewlines) == nil } func textDidChangeInLoginAlert() { if let email = textFields?[0].text, let password = textFields?[1].text, let action = actions.last { action.isEnabled = isValidEmail(email) && isValidPassword(password) } } } // ViewController override func viewDidLoad() { super.viewDidLoad() let alert = UIAlertController(title: "Please Log In", message: nil, prefernetworkingStyle: .alert) alert.addTextField { $0.placeholder = "Email" $0.addTarget(alert, action: #selector(alert.textDidChangeInLoginAlert), for: .editingChanged) } alert.addTextField { $0.placeholder = "Password" $0.isSecureTextEntry = true $0.addTarget(alert, action: #selector(alert. textDidChangeInLoginAlert), for: .editingChanged) } alert.addAction(UIAlertAction(title: "Cancel", style: .cancel)) let loginAction = UIAlertAction(title: "Submit", style: .default) { [unowned self] _ in guard let email = alert.textFields?[0].text, let password = alert.textFields?[1].text else { return } // Should never happen // Perform login action } loginAction.isEnabled = false alert.addAction(loginAction) present(alert, animated: true) } 

introduzca la descripción de la imagen aquí

Esto se puede lograr a través de NSNotificationCenter antes de mostrar el controller de alerta, todo lo que tiene que hacer es pedir al centro de notifications que observe la notificación para UITextFieldTextDidChangeNotification y debe ser bueno,

A continuación se presenta la implementación para el mismo

 @IBAction func showAlert(sender: AnyObject) { var alert = UIAlertController(title: "New user", message: "Add a new user", prefernetworkingStyle: .Alert) let saveAction = UIAlertAction(title: "Save", style: .Default) { (action: UIAlertAction!) -> Void in println("do your stuff here") } saveAction.enabled = false let cancelAction = UIAlertAction(title: "Cancel", style: .Default) { (action: UIAlertAction!) -> Void in } alert.addTextFieldWithConfigurationHandler { (textFieldName: UITextField!) in textFieldName.placeholder = "Enter full name" } alert.addTextFieldWithConfigurationHandler { (textFieldEmail: UITextField!) in textFieldEmail.placeholder = "Enter valid email adress" textFieldEmail.keyboardType = .EmailAddress } // adding the notification observer here NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object:alert.textFields?[0], queue: NSOperationQueue.mainQueue()) { (notification) -> Void in let textFieldName = alert.textFields?[0] as! UITextField let textFieldEmail = alert.textFields![1] as! UITextField saveAction.enabled = self.isValidEmail(textFieldEmail.text) && !textFieldName.text.isEmpty } NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object:alert.textFields?[1], queue: NSOperationQueue.mainQueue()) { (notification) -> Void in let textFieldEmail = alert.textFields?[1] as! UITextField let textFieldName = alert.textFields?[0] as! UITextField saveAction.enabled = self.isValidEmail(textFieldEmail.text) && !textFieldName.text.isEmpty } alert.addAction(saveAction) alert.addAction(cancelAction) presentViewController(alert, animated: true, completion: nil) } // email validation code method func isValidEmail(testStr:String) -> Bool { let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}" if let emailTest = NSPnetworkingicate(format:"SELF MATCHES %@", emailRegEx) as NSPnetworkingicate? { return emailTest.evaluateWithObject(testStr) } return false } 

Regístrese para las notifications de cambio de campo de text y valide los campos de text allí:

 //... alert.addTextFieldWithConfigurationHandler { (textFieldEmail: UITextField!) in textFieldEmail.placeholder = "Enter valid email adress" textFieldEmail.keyboardType = .EmailAddress } let textFieldValidationObserver: (NSNotification!) -> Void = { _ in let textFieldName = alert.textFields![0] as! UITextField let textFieldEmail = alert.textFields![1] as! UITextField saveAction.enabled = self.isValidEmail(textFieldEmail.text) && textFieldName.text.length > 0 } // Notifications for textFieldName changes NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object: alert.textFields![0], // textFieldName queue: NSOperationQueue.mainQueue(), usingBlock: textFieldValidationObserver) // Notifications for textFieldEmail changes NSNotificationCenter.defaultCenter().addObserverForName(UITextFieldTextDidChangeNotification, object: alert.textFields![1], // textFieldEmail queue: NSOperationQueue.mainQueue(), usingBlock: textFieldValidationObserver) alert.addAction(saveAction) //... 

Puede usar el siguiente código para validar TextFields en un UIAlertController: –

Paso 1:

 Declare "email_TF" to your viewcontroller.h for example: @property(strong,nonatomic)UITextField *email_TF; 

Paso 2:

 UIAlertController *alert= [UIAlertController alertControllerWithTitle:@"Forgot Password?" message:nil prefernetworkingStyle:UIAlertControllerStyleAlert]; [alert addTextFieldWithConfigurationHandler: ^(UITextField *textField){ textField.placeholder= @"Enter Your Valid Email"; textField.autocorrectionType= UITextAutocorrectionTypeYes; textField.keyboardType= UIKeyboardTypeEmailAddress; email_TF= textField; }]; 

Paso 3:

 UIAlertAction *noButton= [UIAlertAction actionWithTitle:@"No, thanks" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action){ //Handel no, thanks button }]; [alert addAction:noButton]; UIAlertAction *yesButton= [UIAlertAction actionWithTitle:@"Yes, please" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action){ //Handel your yes please button action here NSLog(@"%@", email_TF.text); if(email_TF.text.length>0){// NSString *emailString= email_TF.text; NSString *emailReg= @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"; NSPnetworkingicate *emailTest= [NSPnetworkingicate pnetworkingicateWithFormat:@"SELF MATCHES %@",emailReg]; if(([emailTest evaluateWithObject:emailString]!=YES) || [emailString isEqualToString:@""]){ UIAlertView *loginalert= [[UIAlertView alloc] initWithTitle:@"Forgot Password !" message:@"\nPlease enter valid Email (example@example.com format) ." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles: nil]; [loginalert show]; }else{ NSLog(@"your TextField successfully validated"); } }else{ UIAlertView *alert= [[UIAlertView alloc] initWithTitle:@"Forgot Password !" message:@"\nPlease Enter Your Email..." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } }]; [alert addAction:yesButton]; 

Etapa 4:

 [self presentViewController:alert animated:YES completion:nil]; 

Implementé una subclass UIAlertController que le permite agregar un controller en los cambios de campo de text cuando lo agrega a la alerta:

 public class TextEnabledAlertController: UIAlertController { private var textFieldActions = [UITextField: ((UITextField)->Void)]() func addTextField(configurationHandler: ((UITextField) -> Void)? = nil, textChangeAction:((UITextField)->Void)?) { super.addTextField(configurationHandler: { (textField) in configurationHandler?(textField) if let textChangeAction = textChangeAction { self.textFieldActions[textField] = textChangeAction textField.addTarget(self, action: #selector(self.textFieldChanged), for: .editingChanged) } }) } @objc private func textFieldChanged(sender: UITextField) { if let textChangeAction = textFieldActions[sender] { textChangeAction(sender) } } } 

Entonces, para su caso, la única cosa adicional que debe agregarse es llamar a la function isValidEmail en el controller textChangeAction:

  alert.addTextField(configurationHandler: { (textField) in // things you want to configure on the textfield }) { (textField) in saveAction.isEnabled = isValidEmail(textField.text ?? "") } 

Primero, debe agregar algunas variables a su class:

 private weak var saveAction : UIAlertAction? private weak var textFieldName : UITextField? private weak var textFieldEmail : UITextField? private var validName = false private var validEmail = false 

Luego, cuando desee configurar el controller de alerta (solo pegué las cosas que necesitan cambiarse):

  alert.addTextFieldWithConfigurationHandler { (textFieldName: UITextField!) in textFieldName.placeholder = "Enter full name" textFieldName.delegate = self self.textFieldName = textFieldName } alert.addTextFieldWithConfigurationHandler { (textFieldEmail: UITextField!) in textFieldEmail.placeholder = "Enter valid email adress" textFieldEmail.keyboardType = .EmailAddress textFieldEmail.delegate = self self.textFieldEmail = textFieldEmail } let saveAction = UIAlertAction(title: "Save", style: .Default) { (action: UIAlertAction!) -> Void in // here you are sure the name and email are correct let name = (alert.textFields[0] as! UITextField).text let email = (alert.textFields[1] as! UITextField).text } saveAction.enabled = false self.saveAction = saveAction 

Finalmente, debe implementar este método de delegado:

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let newText = NSString(string: textField.text).stringByReplacingCharactersInRange(range, withString: string) if textField == self.textFieldName { // validate newText for the name requirements validName = self.validateName(newText) } else if textField == self.textFieldEmail { // validate newText for the email requirements validEmail = self.validateEmail(newText) } self.saveAction?.enabled = validEmail && validName return true }