J'ajoute un UITextField
à un UIAlertController
, qui apparaît comme un AlertView
. Avant de rejeter le UIAlertController
, je veux valider l'entrée du UITextField
. Sur la base de la validation, je souhaite ignorer le UIAlertController
ou non. Mais je ne sais pas comment empêcher l'action de rejet de UIAlertController
lorsqu'un bouton est enfoncé. Quelqu'un a-t-il résolu ce problème ou des idées par où commencer? Je suis allé sur Google mais pas de chance:/Merci!
Vous avez raison: si l'utilisateur peut appuyer sur un bouton de votre alerte, l'alerte sera rejetée. Vous voulez donc empêcher l'utilisateur d'appuyer sur le bouton! Il s'agit simplement de désactiver vos boutons UIAlertAction. Si une action d'alerte est désactivée, l'utilisateur ne peut pas la toucher pour la rejeter.
Pour combiner cela avec la validation de champ de texte, utilisez une méthode déléguée de champ de texte ou une méthode d'action (configurée dans le gestionnaire de configuration du champ de texte lorsque vous le créez) pour activer/désactiver les UIAlertActions de manière appropriée en fonction du texte qui a (ou n'a pas) été entré .
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 mis l'action OK dans le monde désactivé:
(alert.actions[1] as UIAlertAction).enabled = false
Par la suite, l'utilisateur ne peut pas appuyer sur OK sauf s'il y a 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 matt sans traverser la hiérarchie de vues. Cela tient plutôt l'action elle-même comme une variable faible. 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")
}
Criboter la réponse de @ Matt, voici comment j'ai fait la même chose dans Obj-C
- (BOOL)textField: (UITextField*) textField shouldChangeCharactersInRange: (NSRange) range replacementString: (NSString*)string
{
NSString *newString = [textField.text stringByReplacingCharactersInRange: range withString: string];
// check string length
NSInteger newLength = [newString 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;
// <check for duplicates, here>
okAction.enabled = !duplicateName;
}
return (okToChange);
}
Je me rends compte que c'est dans Objectiv-C mais cela montre le principal. Je mettrai à jour cela avec une version Swift plus tard.
Vous pouvez également faire de même en utilisant un bloc comme cible.
Ajoutez une propriété à votre ViewController
pour que le bloc (fermeture pour Swift) ait une référence forte
@property (strong, nonatomic) id textValidationBlock;
Créez ensuite le AlertViewController
comme ceci:
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];