如果模态 ViewController 呈现样式为 UIModalPresentationFormSheet,iPad 键盘不会关闭

发布于 2024-09-12 07:41:50 字数 1734 浏览 12 评论 0原文

注意

请参阅已接受的答案(不是投票最高的答案)以获取 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];

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

天荒地未老 2024-09-19 07:41:50

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

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

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

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

更新:

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

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

这可以解决问题。

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.

太傻旳人生 2024-09-19 07:41:50

如果您使用 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。

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.

最笨的告白 2024-09-19 07:41:50

在以模态方式呈现的视图控制器中,只需覆盖 disablesAutomaticKeyboardDismissal 即可返回 NO

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

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

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}
大姐,你呐 2024-09-19 07:41:50

我通过使用 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];

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];
无需解释 2024-09-19 07:41:50

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

如果有修复的话那就太好了,但目前还可以。您可以将其楔入 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 和所有这些方法被调用时请小心这一点。就像我说的,它并不漂亮,但确实有效。

-亚当

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

属性 2024-09-19 07:41:50

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

可能不是最好的解决方案,但它非常简单,并且不需要任何花哨的技巧,这些技巧会在下一个主要 iOS 版本中出现:)

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 :)

灵芸 2024-09-19 07:41:50

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

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

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)];
好听的两个字的网名 2024-09-19 07:41:50

我发现 disablesAutomaticKeyboardDismissal 和添加 disablesAutomaticKeyboardDismissal 函数对模式对话框中的 UITextField 不起作用。

屏幕键盘不会消失。

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

似乎当 iOS 发现没有启用任何 UITextField 控件时,它就会摆脱键盘。

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.

若言繁花未落 2024-09-19 07:41:50

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

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?

执笔绘流年 2024-09-19 07:41:50

也许不返回“否”,而是返回“是”。所以它可以消失。

并且您的 textFieldShouldEndEditing 也返回 YES?

为什么你要解雇[nextResponder变成FirstResponder]?!抱歉我现在明白了

我还有一些 UITextView
都有其“可编辑”
属性设置为 FALSE。

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

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.

初见 2024-09-19 07:41:50

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

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

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

花开柳相依 2024-09-19 07:41:50

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

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

花伊自在美 2024-09-19 07:41:50
Swift 4.1:
extension UINavigationController {
   override open var disablesAutomaticKeyboardDismissal: Bool {
      return false
   }
}
Swift 4.1:
extension UINavigationController {
   override open var disablesAutomaticKeyboardDismissal: Bool {
      return false
   }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文