example - uialertcontroller swift 3
Evitar el despido de UIAlertController (4)
Estoy agregando un UITextField
a un UIAlertController
, que aparece como una AlertView
. Antes de UIAlertController
el UIAlertController
, quiero validar la entrada de UITextField
. En función de la validación, deseo descartar UIAlertController
o no. Pero no tengo ni idea de cómo evitar la acción de UIAlertController
del UIAlertController
cuando se presiona un botón. ¿Alguien ha resuelto este problema o alguna idea de por dónde empezar? Fui a google pero no tuve suerte: / ¡Gracias!
Comprimiendo la respuesta de @ Matt, así es como hice lo mismo en 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);
}
Estás en lo correcto: si el usuario puede presionar un botón en tu alerta, la alerta será descartada. ¡Entonces quiere evitar que el usuario toque el botón! Todo es solo cuestión de desactivar tus botones de UIAlertAction. Si una acción de alerta está deshabilitada, el usuario no puede tocarla para descartarla.
Para combinar esto con validación de campo de texto, use un método de delegado de campo de texto o método de acción (configurado en el controlador de configuración del campo de texto cuando lo crea) para habilitar / deshabilitar las UIAlertActions apropiadamente dependiendo de qué texto se haya (o no) ingresado .
Aquí hay un ejemplo. Creamos el campo de texto de esta manera:
alert.addTextFieldWithConfigurationHandler {
(tf:UITextField!) in
tf.addTarget(self, action: "textChanged:", forControlEvents: .EditingChanged)
}
Tenemos una acción Cancelar y una acción OK, y trajimos la acción OK al mundo deshabilitado:
(alert.actions[1] as UIAlertAction).enabled = false
Posteriormente, el usuario no puede pulsar Aceptar a menos que haya texto real en el campo de texto:
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 != "")
}
EDITAR Aquí está la versión actual (Swift 3.0.1 y posterior) del código anterior:
alert.addTextField { tf in
tf.addTarget(self, action: #selector(self.textChanged), for: .editingChanged)
}
y
alert.actions[1].isEnabled = false
y
@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 != "")
}
Me doy cuenta de que esto está en Objectiv-C pero muestra el principal. Voy a actualizar esto con una versión rápida más tarde.
También podría hacer lo mismo usando un bloque como objetivo.
Agregue una propiedad a su ViewController
para que el bloque (cierre para swift) tenga una referencia fuerte
@property (strong, nonatomic) id textValidationBlock;
A continuación, cree AlertViewController
como 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];
Simplifiqué la respuesta de Matt sin cruzar la jerarquía de vistas. Esto es la celebración de la acción en sí misma como una variable débil en su lugar. Este es un ejemplo completamente funcional:
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")
}