El teclado del iPad no se cerrará si el estilo de presentación modal ViewController es UIModalPresentationFormSheet

Nota:

Vea la respuesta aceptada (no la más votada) para la solución a partir de iOS 4.3.

Esta pregunta se trata de un comportamiento descubierto en el teclado del iPad, donde se rechaza si se muestra en un cuadro de diálogo modal con un controlador de navegación.

Básicamente, si presento el controlador de navegación con la siguiente línea como a continuación:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet; 

El teclado se niega a ser descartado. Si comento esta línea, el teclado se va bien.

Tengo dos textFields, nombre de usuario y contraseña; nombre de usuario tiene un botón Siguiente y la contraseña tiene un botón Hecho. El teclado no desaparecerá si lo presento en un controlador de navegación modal.

TRABAJOS

 broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil]; [self.view addSubview:b.view]; 

NO FUNCIONA

 broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil]; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:b]; navigationController.modalPresentationStyle = UIModalPresentationFormSheet; navigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; [self presentModalViewController:navigationController animated:YES]; [navigationController release]; [b release]; 

Si elimino la parte del controlador de navegación y presento ‘b’ como un controlador de vista modal por sí mismo, funciona. ¿Es el controlador de navegación el problema?

TRABAJOS

 broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil]; b.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; [self presentModalViewController:b animated:YES]; [b release]; 

TRABAJOS

 broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil]; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:b]; [self presentModalViewController:navigationController animated:YES]; [navigationController release]; [b release]; 

En viewController que se presenta de forma modal, sobrescribe disablesAutomaticKeyboardDismissal para devolver siempre NO

 - (BOOL)disablesAutomaticKeyboardDismissal { return NO; } 

Esto ha sido clasificado como “funciona según lo previsto” por los ingenieros de Apple. Archivé un error para esto hace un tiempo. Su razonamiento es que el usuario a menudo va a ingresar datos en forma modal, por lo que intentan ser “útiles” y mantener el teclado visible donde, normalmente, varias transiciones dentro de la vista modal pueden hacer que el teclado se muestre u oculte repetidamente.

editar: aquí está la respuesta de un ingeniero de Apple en los foros de desarrolladores:

¿Su perspectiva se presentó con el estilo UIModalPresentationFormSheet? Para evitar animaciones frecuentes de entrada y salida, el teclado algunas veces permanecerá en la pantalla incluso cuando no haya una primera respuesta. Esto no es un error.

Esto está causando problemas a mucha gente (incluido yo mismo), pero por el momento no parece haber una forma de evitarlo.

ACTUALIZAR:

En iOS 4.3 y posterior, ahora puede implementar `-disablesAutomaticKeyboardDismissal ‘en su controlador de vista para devolver NO:

 - (BOOL)disablesAutomaticKeyboardDismissal { return NO; } 

Esto soluciona el problema.

Tenga cuidado si muestra el modal con un UINavigationController . Luego debe configurar el disablesAutomaticKeyboardDismissal del disablesAutomaticKeyboardDismissal en el controlador de navegación y no en el controlador de vista. Puedes hacer esto fácilmente con categorías.

Archivo: UINavigationController + KeyboardDismiss.h

 #import  @interface UINavigationController (KeyboardDismiss) - (BOOL)disablesAutomaticKeyboardDismissal; @end 

Archivo: UINavigationController + KeyboardDismiss.m

 #import "UINavigationController+KeyboardDismiss.h" @implementation UINavigationController(KeyboardDismiss) - (BOOL)disablesAutomaticKeyboardDismissal { return NO; } @end 

No olvide importar la categoría en el archivo donde usa el UINavigationController.

Lo resolví utilizando el estilo de presentación UIModalPresentationPageSheet y UIModalPresentationPageSheet tamaño inmediatamente después de presentarlo. Al igual que:

 viewController.modalPresentationStyle = UIModalPresentationPageSheet; viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; [self presentModalViewController:viewController animated:YES]; viewController.view.superview.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; viewController.view.superview.frame = CGRectMake( viewController.view.superview.frame.origin.x, viewController.view.superview.frame.origin.y, 540.0f, 529.0f ); viewController.view.superview.center = self.view.center; [viewController release]; 

Si alternas una pantalla modal diferente, puedes hacer que desaparezca el teclado. No es bonito y no se anima, pero puedes lograr que desaparezca.

Sería genial si hubiera una solución, pero por ahora esto funciona. Puedes UIViewController en una categoría en UIViewController y llamarlo cuando quieras que el teclado desaparezca:

 @interface _TempUIVC : UIViewController @end @implementation _TempUIVC - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; } @end @implementation UIViewController (Helpers) - (void)_dismissModalViewController { [self dismissModalViewControllerAnimated:NO]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil]; [self release]; } - (void)forceKeyboardDismissUsingModalToggle:(BOOL)animated { [self retain]; _TempUIVC *tuivc = [[_TempUIVC alloc] init]; tuivc.modalPresentationStyle = UIModalPresentationCurrentContext; [self presentModalViewController:tuivc animated:animated]; if (animated) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_dismissModalViewController) name:UIKeyboardDidHideNotification object:nil]; } else [self _dismissModalViewController]; [tuivc release]; } @end 

Tenga cuidado con esto sin embargo cuando vea DidAppear / viewDidDisappear y se invoquen todos esos métodos. Como dije, no es bonito, pero funciona.

-Adán

También puede solucionar esto en una aplicación universal simplemente verificando la expresión idiomática y, si se trata de un iPad, no muestre automáticamente el teclado y deje que el usuario toque lo que quiera editar.

Puede que no sea la mejor solución, pero es muy sencillo y no necesita ningún truco de lujo que rompa con el próximo lanzamiento importante de iOS 🙂

Para aquellos que tienen problemas con UINavigationController, vea mi respuesta a una pregunta similar aquí: https://stackoverflow.com/a/10507689/321785

Editar: Considero que esto es una mejora a la solución de Miha Hribar (ya que la decisión se está llevando a cabo donde debería), y en contraposición al comentario de Pascal sobre una categoría en UIViewController

Coloque este código en su vista. Desaparecerá: el método del controlador actual es otra forma de solucionarlo:

 Class UIKeyboardImpl = NSClassFromString(@"UIKeyboardImpl"); id activeInstance = [UIKeyboardImpl performSelector:@selector(activeInstance)]; [activeInstance performSelector:@selector(dismissKeyboard)]; 

Estoy seguro de que lo ha visto, pero está seguro de que su clase de controlador está conectada correctamente como delegado UITextField, ¿verdad?

tal vez no devuelva NO, pero SÍ. Entonces puede desaparecer

¿Y tiene un textFieldShouldEndEditing devuelve SÍ?

¿ Y por qué estás disparando [nextResponder becomeFirstResponder] ? lo siento, veo ahora

También tengo un número de UITextViews que tienen su propiedad “editable” configurada en FALSE.

¿Podemos suponer que ninguno de ellos, por casualidad, tiene un valor de tag de secondField.tag+1 ? Si es así, les está diciendo que se conviertan en los primeros en responder, en lugar de renunciar al primer respondedor. Quizás ponga algo de NSLog () en esa estructura.

puede no ser una solución perfecta, pero funciona
[self.view endEditing: YES];
desde donde se implemente su botón o gesto para presentar modal

Descubrí que disablesAutomaticKeyboardDismissal y agregar una función UITextField no funcionaba para mi UITextField en un cuadro de diálogo modal.

El teclado en pantalla simplemente no desaparecerá.

Mi solución fue desactivar todos los controles de entrada de texto en mi cuadro de diálogo, luego reactivar los relevantes una fracción de segundo más tarde.

Parece que cuando iOS ve que ninguno de los controles UITextField está habilitado, entonces se deshace del teclado.

 Swift 4.1: extension UINavigationController { override open var disablesAutomaticKeyboardDismissal: Bool { return false } }