By Kalle


2010-07-30 14:17:55 8 Comments

Note:

See accepted answer (not top voted one) for solution as of iOS 4.3.

This question is about a behavior discovered in the iPad keyboard, where it refuses to be dismissed if shown in a modal dialog with a navigation controller.

Basically, if I present the navigation controller with the following line as below:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

The keyboard refuses to be dismissed. If I comment out this line, the keyboard goes away fine.

...

I've got two textFields, username and password; username has a Next button and password has a Done button. The keyboard won't go away if I present this in a modal navigation controller.

WORKS

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

DOES NOT WORK

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];

If I remove the navigation controller part and present 'b' as a modal view controller by itself, it works. Is the navigation controller the problem?

WORKS

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

WORKS

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

13 comments

@Sebastian H 2011-03-31 17:12:58

In the view controller that is presented modally, just override disablesAutomaticKeyboardDismissal to return NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

@Kalle 2011-03-31 19:03:18

Yep, since 4.3 this seems to be the case. Will update the question. Thanks!

@pottedmeat 2013-09-24 19:50:16

This needs to be added to the navigation controller

@James Laurenstin 2013-12-01 03:50:21

Yes, works when you overwrite it in the NavigationController. That's the only thing that actually worked for me.

@SomaMan 2014-06-24 10:27:43

Life saver! Why does Apple do stuff like this? Surely it should default to NO & allow us to change it if we really want to

@Jorge Arimany 2015-10-16 17:54:02

Not working on UIViewController derived class, disablesAutomaticKeyboardDismissal is never called

@fivewood 2018-02-01 05:29:42

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

@azdev 2010-12-15 22:14:14

I solved this by using the UIModalPresentationPageSheet presentation style and resizing it immediately after I present it. Like so:

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];

@toofah 2011-01-07 16:53:14

Hmmm...this is not quite right...resizing causes the modal to paint funny...it's like it squishes the content down to fit in the new size box or something...everything looks funny. :(

@toofah 2011-01-07 17:07:52

There are also rotation problems with this one...if you rotate while this modal is up it will shrink/grow as if it were a full page view

@azdev 2011-01-08 19:53:50

toofah, I edited the code to deal with the shrinking/growing problem when rotating; just a matter of giving the superview a flexible top and bottom margin. I'm not sure I'm seeing the other behavior.

@V1ru8 2011-04-07 15:38:00

this works only as long as you don't push a other view on top of this one. Because when you close the view pushed above the UIModalPresentationPageSheet presented view, it's back to it's original size.

@jeswang 2012-08-23 08:00:25

It worked. But the word in the view looks a little blur. I don't know why.

@Frade 2012-12-03 17:19:09

I usually use the same solution for resizing a modalview. But I realize that it doesn't work for iOS 6. The view always gets stuck at the top of parent view. Any solution?? thanks

@Mike Gledhill 2015-06-22 08:12:08

I found that disablesAutomaticKeyboardDismissal and adding a disablesAutomaticKeyboardDismissal function didn't work for my UITextField in a modal dialog.

The onscreen keyboard just wouldn't go away.

My solution was to disable all text-input controls in my dialog, then re-enable the relevant ones a fraction of a second later.

It seems as though when iOS sees that none of the UITextField controls are enabled, then it does get rid of the keyboard.

@Tanuj Jagoori 2015-05-08 08:41:12

may be not a perfect solution ,but works
[self.view endEditing:YES];
from wherever your button or gesture is implemented to present modal

@Story 2014-05-24 09:08:07

Put this code in your viewWillDisappear: method of current controller is another way to fix this:

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

@Chris Trahey 2012-05-08 23:10:13

For those having trouble with UINavigationController, see my answer to a similar question here: https://stackoverflow.com/a/10507689/321785

Edit: I consider this an improvement to Miha Hribar's solution (since the decision is taking place where it should), and as opposed to Pascal's comment regarding a category on UIViewController

@Maciej Swic 2012-03-06 22:38:02

You could also work around this in a universal app by simply checking the idiom and if it's an iPad, don't pop up the keyboard automatically at all and let the user tap whatever they want to edit.

May not be the nicest solution but it's very straightforward and doesn't need any fancy hacks that will break with the next major iOS release :)

@Mike Weller 2010-08-02 10:13:59

This has been classified as "works as intended" by Apple engineers. I filed a bug for this a while back. Their reasoning is that the user is often going to be entering data in a modal form so they are trying to be "helpful" and keep the keyboard visible where ordinarily various transitions within the modal view can cause the keyboard to show/hide repeatedly.

edit: here is the response of an Apple engineer on the developer forums:

Was your view by any chance presented with the UIModalPresentationFormSheet style? To avoid frequent in-and-out animations, the keyboard will sometimes remain on-screen even when there is no first responder. This is not a bug.

This is giving a lot of people problems (myself included) but at the moment there doesn't seem to be a way to work around it.

UPDATE:

In iOS 4.3 and later, you can now implement `-disablesAutomaticKeyboardDismissal' on your view controller to return NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

This fixes the issue.

@Kalle 2010-08-02 10:29:29

pause Wow, okay. Thanks a lot for the heads up. Damn Apple.. :(

@Shaggy Frog 2010-09-02 02:08:34

Did you submit a bug report to Apple? I have done so under ID# 8384423. I have also submitted a sample application to reproduce the behaviour.

@Kalle 2010-09-16 16:01:56

MishieMoo: nice! Glad Apple are acknowledging that, at least.

@PostCodeism 2010-11-26 03:06:13

Wow, that is retarded. You'd think that they'd create a flexible solution that would enable us to meet our client's use cases...but instead they create the use case for the client they don't even know! :S

@Kalle 2011-03-31 19:06:37

As of iOS 4.3 there is now a disablesAutomaticKeyboardDismissal method which fixes this problem.

@R. Dewi 2011-09-21 02:06:47

i try that disablesAutomaticKeyboardDismissal method, but it still did not solve the problem, how to solve it?

@Snips 2012-10-26 23:25:18

Unfortunately, this solution is broken again in iOS 6 :-(

@Pascal 2012-10-27 00:20:58

@Snips: You need to create a UINavigationController subclass that overrides disablesAutomaticKeyboardDismissal to return NO and use this as the navigation controller when you present a modal form sheet. See the answer from @miha-hribar below.

@Miha Hribar 2011-05-10 11:42:18

Be careful if you are displaying the modal with a UINavigationController. You then have to set the disablesAutomaticKeyboardDismissal on the navigation controller and not on the view controller. You can easily do this with categories.

File: UINavigationController+KeyboardDismiss.h

#import <Foundation/Foundation.h>

@interface UINavigationController (KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal;

@end

File: UINavigationController+KeyboardDismiss.m

#import "UINavigationController+KeyboardDismiss.h"

@implementation UINavigationController(KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}

@end

Do not forget to import the category in the file where you use the UINavigationController.

@DarkDust 2011-10-26 12:55:52

+1, finally I see the missing piece of information for this issue highlighted: that one needs to override disablesAutomaticKeyboardDismissal of UINavigationController, not the own view controller, to fix this issue.

@Justin 2011-12-02 11:50:52

Nice! Just what I needed. Thank you.

@imnk 2012-04-17 09:26:03

Perfect. Not clear from official docs but makes sense due to the UINavigationController being in the responder chain. Excellent answer. Thank you!

@Mark 2012-05-18 21:20:53

This bit of knowledge fixed my problem immediately. Thanks!

@Snips 2012-10-27 14:42:03

I'm presenting a modal dialog from a UISplitViewController. I've tried the above code, but substituted UISplitViewController for UINavigationController, but it still doesn't work. Should this method also work on a UISplitViewController?

@Jono 2013-01-19 23:08:52

Thanks for providing a solution that actually works with an explanation that's succinct and easy to follow.

@HusseinB 2013-04-09 20:24:10

i created this category and imported it in the view controller that i'll be using. now what? do i need to override anything or add any code to dismiss the keyboard in the viewController?

@sean woodward 2013-04-18 20:32:11

It's not a good idea to implement a duplicate method in a category. You can never be certain which implementation will be called, so at best you can expect inconsistent behavior. Better to inherit from UINavigationController and override the method in your custom class.

@Natan R. 2013-07-18 08:40:16

Man, how didn't I think about this solution?! Usually, as sean said, it's better to use subclass in these cases...

@Adam 2010-12-09 12:22:59

If you toggle a different modal display you can get the keyboard to disappear. It's not pretty and it doesn't animate down, but you can get it to go away.

It'd be great if there was a fix, but for now this works. You can wedge it in a category on UIViewController and call it when you want the keyboard gone:

@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

Be careful with this though as you viewDidAppear / viewDidDisappear and all those methods get called. Like I said, it's not pretty, but does work.

-Adam

@mvds 2010-07-30 14:20:32

maybe don't return NO, but YES. So it can go away.

And you have a textFieldShouldEndEditing returning YES as well?

And why are you firing [nextResponder becomeFirstResponder]?! sorry i see now

I also have a number of UITextViews which all have their "editable" property set to FALSE.

May we assume none of them, by any chance, has a tag value of secondField.tag+1? If so, you're telling them to become first responder, instead of resigning the first responder. Maybe put some NSLog() in that if structure.

@Kalle 2010-07-30 14:36:05

NO = don't insert newline, from what I can tell. And setting it to YES didn't fix it.

@mvds 2010-07-30 14:51:04

A UITextField, being one line by definition, doesn't do much with newlines, I think. So it's more about processing pressing of the Return/Done button, as stated in the docs.

@mvds 2010-07-30 15:04:56

Are you very sure you hooked everything up the right way? Have you put an NSLog("tf %x / method ...",textField); in all delegate functions?

@Kalle 2010-08-01 08:34:44

Well, the delegate functions are called appropriately, and they wouldn't be if the delegate wasn't set up appropriately. And the NSLog gives an EXC_BAD_ACCESS. Also warns me about it being incompatible type in XCode.

@Kalle 2010-08-01 10:27:05

D'oh. Sorry, should've seen that myself. I've updated the answer above with the results of these NSLogs since formatting will gook itself in comm..

@mvds 2010-08-01 10:42:11

put some NSLog's within the if as well to see what's going on exactly. see my updated answer btw.

@mvds 2010-08-01 13:43:21

Can't you just zip the entire thing and post it somewhere? I want to believe "all is right but it doesn't work" but I'd like to see it happening with my own eyes...

@Kalle 2010-08-01 14:44:05

Can't, because it's a work project and all that, but what I'll do is (and I should do this, anyway) make a new project and merge this part of it over. Presumably it will WORK, but in the off chance that it doesn't, I can post that project. Give me a day or so to do it though. Will update answer and such when it's done.

@Kalle 2010-08-02 09:32:44

Huh! While working on getting this into its own project by itself, I realized the following: the keyboard DOES GO AWAY if the view IS NOT A MODAL VIEW. If the view is, the keyboard stays; if the view is not, the keyboard goes away. Still no idea how to solve it but will post the two versions above in my answer in a sec...

@Kalle 2010-08-02 10:07:07

I've updated the answer above and cleaned it up a bit. In summary, the following line is causing the problem: navigationController.modalPresentationStyle = UIModalPresentationFormSheet; -- if I remove it, the keyboard will dismiss fine. I can only presume this is a bug.

@Neal L 2010-08-01 04:58:24

I'm sure you have looked at this, but you are sure that your controller class is properly hooked up as the UITextField delegate, right?

@Kalle 2010-08-01 08:35:00

I set it manually myself, and the delegate methods are called, so yeah.

Related Questions

Sponsored Content

94 Answered Questions

35 Answered Questions

[SOLVED] iOS - Dismiss keyboard when touching outside of UITextField

8 Answered Questions

4 Answered Questions

[SOLVED] Detecting of popover dismiss

5 Answered Questions

[SOLVED] Strange warning dismissing modal view controller

1 Answered Questions

1 Answered Questions

[SOLVED] Dismissing modal view controller

1 Answered Questions

Weird Behavior on dismissing Modal View Controller

1 Answered Questions

Sponsored Content