Empêcher le renvoi de UIAlertController

UITextField un UITextField à un UIAlertController , qui apparaît comme un AlertView . Avant de rejeter UIAlertController , je souhaite valider l’entrée de UITextField . Sur la base de la validation, je souhaite rejeter UIAlertController ou non. Mais je ne sais pas comment empêcher l’action de rejet de l’ UIAlertController lorsqu’un bouton est pressé. Quelqu’un at-il résolu ce problème ou des idées par où commencer? Je suis allé à Google mais pas de chance: / Merci!

Vous avez raison: si l’utilisateur peut appuyer sur un bouton dans votre alerte, l’alerte sera rejetée. Donc, vous voulez empêcher l’utilisateur d’appuyer sur le bouton! Il suffit simplement de désactiver vos boutons UIAlertAction. Si une action d’alerte est désactivée, l’utilisateur ne peut pas appuyer dessus pour la supprimer.

Pour combiner cela avec la validation de champ de texte, utilisez une méthode déléguée ou une méthode d’action de champ de texte (configurée dans le gestionnaire de configuration du champ de texte lors de sa création) pour activer / désactiver les UIAlertActions en fonction du texte entré (ou non) .

Voici un exemple. Nous avons créé le champ de texte comme ceci:

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

Nous avons une action Annuler et une action OK, et nous avons désactivé l’action OK dans le monde:

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

Par la suite, l’utilisateur ne peut pas appuyer sur OK sauf s’il existe du texte dans le champ de texte:

 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 Voici la version actuelle (Swift 3.0.1 et ultérieure) du code ci-dessus:

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

et

 alert.actions[1].isEnabled = false 

et

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

J’ai simplifié la réponse de mat sans voir la vue traversée. Cela maintient l’action elle-même en tant que variable faible à la place. Ceci est un exemple pleinement fonctionnel:

 weak var actionToEnable : UIAlertAction? func showAlert() { let titleStr = "title" let messageStr = "message" let alert = UIAlertController(title: titleStr, message: messageStr, preferredStyle: UIAlertControllerStyle.Alert) let placeholderStr = "placeholder" alert.addTextFieldWithConfigurationHandler({(textField: UITextField) in textField.placeholder = placeholderStr textField.addTarget(self, action: "textChanged:", forControlEvents: .EditingChanged) }) let cancel = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: { (_) -> Void in }) let action = UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: { (_) -> Void in let textfield = alert.textFields!.first! //Do what you want with the textfield! }) alert.addAction(cancel) alert.addAction(action) self.actionToEnable = action action.enabled = false self.presentViewController(alert, animated: true, completion: nil) } func textChanged(sender:UITextField) { self.actionToEnable?.enabled = (sender.text! == "Validation") } 

Cribbing off de la réponse de @ Matt, voici comment j’ai fait la même chose dans Obj-C

 - (BOOL)textField: (UITextField*) textField shouldChangeCharactersInRange: (NSRange) range replacementSsortingng: (NSSsortingng*)ssortingng { NSSsortingng *newSsortingng = [textField.text ssortingngByReplacingCharactersInRange: range withSsortingng: ssortingng]; // check ssortingng length NSInteger newLength = [newSsortingng length]; BOOL okToChange = (newLength <= 16); // don't allow names longer than this if (okToChange) { // Find our Ok button UIResponder *responder = textField; Class uiacClass = [UIAlertController class]; while (![responder isKindOfClass: uiacClass]) { responder = [responder nextResponder]; } UIAlertController *alert = (UIAlertController*) responder; UIAlertAction *okAction = [alert.actions objectAtIndex: 0]; // Dis/enable Ok button based on same-name BOOL duplicateName = NO; //  okAction.enabled = !duplicateName; } return (okToChange); } 

Je me rends compte que c’est dans Objectiv-C mais il montre le principal. Je vais mettre à jour cela avec une version rapide plus tard.

Vous pouvez également faire la même chose en utilisant un bloc comme cible.

Ajouter une propriété à votre ViewController pour que le bloc (fermeture de swift) ait une référence forte

@property (strong, nonatomic) id textValidationBlock;

Ensuite, créez le AlertViewController comme AlertViewController :

 UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Title" message:@"Message" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]; __weak typeof(self) weakSelf = self; UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [weakSelf doSomething]; }]; [alertController addAction:cancelAction]; [alertController addAction:okAction]; [alertController.actions lastObject].enabled = NO; self.textValidationBlock = [^{ UITextField *textField = [alertController.textFields firstObject]; if (something) { alertController.message = @"Warning message"; [alertController.actions lastObject].enabled = NO; } else if (somethingElse) { alertController.message = @"Another warning message"; [alertController.actions lastObject].enabled = NO; } else { //Validation passed alertController.message = @""; [alertController.actions lastObject].enabled = YES; } } copy]; [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.placeholder = @"placeholder here"; [textField addTarget:weakSelf.textValidationBlock action:@selector(invoke) forControlEvents:UIControlEventEditingChanged]; }]; [self presentViewController:alertController animated:YES completion:nil];