215

笔记:

从 iOS 4.3 开始,请参阅已接受的答案(不是投票最多的答案)以获取解决方案。

这个问题是关于在 iPad 键盘中发现的一种行为,如果在带有导航控制器的模式对话框中显示它,它会拒绝被关闭。

基本上,如果我向导航控制器显示以下行:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

键盘拒绝被解雇。如果我注释掉这一行,键盘就会消失。

...

我有两个文本字段,用户名和密码;用户名有一个下一步按钮,密码有一个完成按钮。如果我在模态导航控制器中显示它,键盘不会消失。

作品

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

不工作

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

如果我删除导航控制器部分并将“b”单独呈现为模态视图控制器,它就可以工作。导航控制器有问题吗?

作品

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

作品

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

13 回答 13

172

这已被 Apple 工程师归类为“按预期工作”。不久前我为此提交了一个错误。他们的理由是,用户通常会以模态形式输入数据,因此他们试图“提供帮助”并保持键盘可见,而模态视图中的各种转换通常会导致键盘重复显示/隐藏。

编辑:这是苹果工程师在开发者论坛上的回复:

您的视图是否有机会以 UIModalPresentationFormSheet 样式呈现?为了避免频繁的进出动画,即使没有第一响应者,键盘有时也会保持在屏幕上。这不是错误。

这给很多人带来了问题(包括我自己),但目前似乎没有办法解决它。

更新:

在 iOS 4.3 及更高版本中,您现在可以在视图控制器上实现 `-disablesAutomaticKeyboardDismissal' 以返回 NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

这解决了这个问题。

于 2010-08-02T10:13:59.287 回答
150

如果您使用UINavigationController. 然后,您必须disablesAutomaticKeyboardDismissal在导航控制器上而不是在视图控制器上设置。您可以使用类别轻松完成此操作。

文件:UINavigationController+KeyboardDismiss.h

#import <Foundation/Foundation.h>

@interface UINavigationController (KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal;

@end

文件:UINavigationController+KeyboardDismiss.m

#import "UINavigationController+KeyboardDismiss.h"

@implementation UINavigationController(KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}

@end

不要忘记在使用 UINavigationController 的文件中导入类别。

于 2011-05-10T11:42:18.647 回答
116

在模态显示的视图控制器中,只需覆盖disablesAutomaticKeyboardDismissal返回NO

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}
于 2011-03-31T17:12:58.900 回答
51

我通过使用UIModalPresentationPageSheet演示样式并在演示后立即调整其大小解决了这个问题。像这样:

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];
于 2010-12-15T22:14:14.620 回答
1

如果您切换不同的模式显示,您可以让键盘消失。它不漂亮,也没有动画,但你可以让它消失。

如果有修复就太好了,但现在这可行。您可以将其楔入一个类别UIViewController并在您希望键盘消失时调用它:

@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

不过,当您 viewDidAppear / viewDidDisappear 并且所有这些方法都被调用时,请注意这一点。就像我说的,它不漂亮,但确实有效。

-亚当

于 2010-12-09T12:22:59.697 回答
1

将此代码放入您的 viewWillDisappear: 当前控制器的方法是解决此问题的另一种方法:

Class UIKeyboardImpl = NSClassFromString(@"UIKeyboardImpl");
id activeInstance = [UIKeyboardImpl performSelector:@selector(activeInstance)];
[activeInstance performSelector:@selector(dismissKeyboard)];
于 2014-05-24T09:08:07.853 回答
1

您也可以通过简单地检查习语在通用应用程序中解决此问题,如果它是 iPad,则根本不要自动弹出键盘,让用户点击他们想要编辑的任何内容。

可能不是最好的解决方案,但它非常简单,不需要任何花哨的 hack 会在下一个主要 iOS 版本中破坏:)

于 2012-03-06T22:38:02.090 回答
1

我发现在模态对话框中 disablesAutomaticKeyboardDismissal添加一个disablesAutomaticKeyboardDismissal功能对我不起作用。UITextField

屏幕键盘不会消失。

我的解决方案是禁用对话框中的所有文本输入控件,然后在几分之一秒后重新启用相关控件。

似乎当 iOS 看到没有UITextField启用任何控件时,它确实摆脱了键盘。

于 2015-06-22T08:12:08.257 回答
0

也许不返回 NO,但 YES。所以它可以消失。

你也有一个textFieldShouldEndEditing返回的“是”吗?

为什么要开枪[nextResponder becomeFirstResponder]?!抱歉,我现在看到了

我还有许多 UITextView,它们的“可编辑”属性都设置为 FALSE。

我们可以假设它们中的任何一个都没tag有价值secondField.tag+1吗?如果是这样,您是在告诉他们成为第一响应者,而不是让第一响应者辞职。也许在 if 结构中放一些 NSLog() 。

于 2010-07-30T14:20:32.210 回答
0

对于那些遇到 UINavigationController 问题的人,请参阅我对类似问题的回答: https ://stackoverflow.com/a/10507689/321785

编辑:我认为这是对 Miha Hribar 解决方案的改进(因为决定发生在它应该发生的地方),而不是 Pascal 关于 UIViewController 上的类别的评论

于 2012-05-08T23:10:13.390 回答
0

我确定您已经看过这个,但您确定您的控制器类已正确连接为 UITextField 委托,对吗?

于 2010-08-01T04:58:24.470 回答
0

可能不是一个完美的解决方案,但有效
[self.view endEditing:YES];
从实现按钮或手势的任何位置呈现模态

于 2015-05-08T08:41:12.640 回答
0
Swift 4.1:
extension UINavigationController {
   override open var disablesAutomaticKeyboardDismissal: Bool {
      return false
   }
}
于 2018-02-01T05:29:42.717 回答