¿Cómo descartar un UIAlertController y el keyboard simultáneamente?

He creado un formulario de logging con un UIAlertController y UIAlertController usado el método addTextFieldWithConfigurationHandler para agregar un campo de text. Pero hay un pequeño problema.

Cuando aparece el formulario, el keyboard y modal aparecen con una animation suave. Al cerrar el formulario, el modal desaparece primero y luego desaparece el keyboard. Esto hace que el keyboard caiga repentinamente hacia abajo.

¿Cómo puedo hacer que el modal y el keyboard desaparezcan graciosamente?

 lazy var alertController: UIAlertController = { [weak self] in let alert = UIAlertController(title: "Alert", message: "This is a demo alert", prefernetworkingStyle: .Alert) alert.addTextFieldWithConfigurationHandler { textField in textField.delegate = self } alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) return alert }() @IBAction func alert() { presentViewController(alertController, animated: true, completion: nil) } func textFieldShouldReturn(textField: UITextField) -> Bool { alertController.dismissViewControllerAnimated(true, completion: nil) return true } 

presentando y descartando

Puede configurar su controller de vista u otro object como delegado de transición de su UIAlertController ( alert.transitioningDelegate ) y crear una animation personalizada para rechazar. Ejemplo de código:

 @interface ViewController () <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning, UITextFieldDelegate> @property (assign, nonatomic) NSTimeInterval keyboardAnimationDuration; @property (assign, nonatomic) CGFloat keyboardHeight; @property (nonatomic, strong) UIAlertController *alertController; @property (nonatomic,strong) id <UIViewControllerTransitioningDelegate> transitioningDelegateForAlertController; @end @implementation ViewController - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)viewDidLoad { [super viewDidLoad]; [self subscribeForKeyboardNotification]; } #pragma mark - Keyboard notifications - (void)subscribeForKeyboardNotification { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil]; } - (void)keyboardWillAppear:(NSNotification *)notification { self.keyboardAnimationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; self.keyboardHeight = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; } #pragma mark - IBAction - (IBAction)showAlertButtonPressed:(id)sender { [self showAlert]; } - (void)showAlert { self.alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:@"This is a demo alert" prefernetworkingStyle:UIAlertControllerStyleAlert]; __weak typeof(self) weakSelf = self; [self.alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { textField.delegate = weakSelf; }]; self.transitioningDelegateForAlertController = self.alertController.transitioningDelegate; self.alertController.transitioningDelegate = self; [self.alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleCancel handler:nil]]; [self presentViewController:self.alertController animated:YES completion:nil]; } #pragma mark - UITextFieldDelegate - (BOOL)textFieldShouldReturn:(UITextField *)textField { [self.alertController dismissViewControllerAnimated:YES completion:nil]; return YES; } #pragma mark - UIViewControllerTransitioningDelegate - (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { return [self.transitioningDelegateForAlertController animationControllerForPresentedController:presented presentingController:presenting sourceController:source]; } - (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed { return self; } #pragma mark - UIViewControllerAnimatedTransitioning - (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext { return self.keyboardAnimationDuration ?: 0.5; } - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext { UIViewController *destination = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; if ([destination isBeingPresented]) [self animatePresentation:transitionContext]; else [self animateDismissal:transitionContext]; } - (void)animatePresentation:(id <UIViewControllerContextTransitioning>)transitionContext { NSTimeInterval transitionDuration = [self transitionDuration:transitionContext]; UIViewController *fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView *container = transitionContext.containerView; fromController.view.frame = container.bounds; toController.view.frame = container.bounds; toController.view.alpha = 0.0f; [container addSubview:toController.view]; [fromController beginAppearanceTransition:NO animated:YES]; [UIView animateWithDuration:transitionDuration animations:^{ toController.view.alpha = 1.0; } completion:^(BOOL finished) { [fromController endAppearanceTransition]; [transitionContext completeTransition:YES]; }]; } - (void)animateDismissal:(id <UIViewControllerContextTransitioning>)transitionContext { NSTimeInterval transitionDuration = [self transitionDuration:transitionContext]; UIViewController *fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; [toController beginAppearanceTransition:YES animated:YES]; [UIView animateWithDuration:transitionDuration animations:^{ fromController.view.alpha = 0.0; [fromController.view endEditing:YES]; CGRect frame = fromController.view.frame; frame.origin.y += self.keyboardHeight / 2; fromController.view.frame = frame; } completion:^(BOOL finished) { [toController endAppearanceTransition]; [transitionContext completeTransition:YES]; }]; } @end 

Resultado:

introduzca la descripción de la imagen aquí

PD: utilicé el delegado de transición de la alerta anterior para la presentación porque no puedo reproducir una animation original. Entonces animatePresentation: método nunca se usa.

Tuve el mismo problema que tú y encontré la solución por casualidad. Probablemente ya no lo necesite, pero por el bien de otros como yo, aquí está la respuesta:

Rápido:

 override func canBecomeFirstResponder() -> Bool { return true } 

C objective:

 - (BOOL)canBecomeFirstResponder { return true; } 

Simplemente agregue este código en el controller de vista que maneja la alerta. Solo probado en veloz.

Su bastante simple.

si su delegado UIAlertController está presente en el controller de vista propia . entonces puede hacerlo en su método delegado para Descartar AlertController. Puedes [youtTextField resignFirstResponder] en tu object UIAlertController que tiene un button para descartarlo. (como Aceptar o Cancelar) por lo que su KeyBoard presentado será rechazado.

No lo intenté, pero funcionará. pero tiene que manejar textField y Alert correctamente.

Supongo que el saltar hacia abajo del UIAlertController es si se descarta después de presionar 'regresar' en el keyboard. Si es así, he encontrado una manera para que la alerta y el keyboard salgan sin problemas de una acción de retorno.

Necesitará declarar UIAlertController dentro del file de class

 @property (strong, nonatomic) UIAlertController *alertController; 

Y también necesitará usar el UITextFieldDelegate con el viewController. Al agregar el campo textField al UIAlertController, aquí es donde tendrá que establecer el delegado del mismo. (débilmente utilizado como está dentro de un bloque)

 @interface ViewController ()<UITextFieldDelegate> 

Dentro del método que está subastando el UIAlertController,

  self.alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:@"This is the message" prefernetworkingStyle:UIAlertControllerStyleAlert]; __weak typeof(self) weakSelf = self; [self.alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { textField.delegate = weakSelf; }]; [self presentViewController:self.alertController animated:YES completion:nil]; 

Agregue este método de delegado UITextField que se activará una vez que se haya presionado el button de retorno en el keyboard. Esto significa que puede realizar una acción para que UIAlertController descarte justo antes de descartar el keyboard, por lo que todo funciona sin problemas.

 -(BOOL)textFieldShouldReturn:(UITextField *)textField{ [self.alertController dismissViewControllerAnimated:YES completion:nil]; return YES; } 

He probado esto y debería funcionar exactamente como lo requieres.

Gracias jim

  - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { [self.view endEditing:YES]; // or you can write [yourtextfield refignFirstResponder] [alertView dismissWithClickedButtonIndex:buttonIndex animated:TRUE]; } 
 - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex==1) { [[alertView textFieldAtIndex:0] resignFirstResponder]; } else { [[alertView textFieldAtIndex:0] resignFirstResponder]; } } 

Use su índice de botones (índice de button Aceptar o Cancelar)

no es necesario hacer nada, solo tienes que implementar tanto código, me funciona, no es necesario declarar ningún tipo de método de delegado

 - (void)showAlert { self.alertController = [UIAlertController alertControllerWithTitle:@"Alert" message:@"Enter Name:" prefernetworkingStyle:UIAlertControllerStyleAlert]; [self.alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { }]; [self.alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleCancel handler:nil]]; [self presentViewController:self.alertController animated:YES completion:nil]; 

}

Swizzle viewWillDisappear método para UIAlertController, y realizar resignFirstResponder en el campo de text correspondiente o llamar a endEditing: en la vista del controller

Estoy usando para este ReactiveCocoa:

  let alert = UIAlertController(title: "", message: "", prefernetworkingStyle: .Alert) alert.addTextFieldWithConfigurationHandler { textField in } let textField = alert.textFields!.first! alert.rac_signalForSelector(#selector(viewWillDisappear(_:))) .subscribeNext { _ in textField.resignFirstResponder() }