简体   繁体   English

当UIAlertView在屏幕上时,无法在UIViewController堆栈中隐藏键盘

[英]Can't hide keyboard in UIViewController stack when UIAlertView is on screen

I just spent most of a day tracking down a very strange case where calling resignFirstResponder on the active UITextField did not hide the keyboard, even though the textfield was the first responder. 我花了大约一天的时间来追踪一个非常奇怪的情况,即在活动的UITextField上调用resignFirstResponder并没有隐藏键盘,即使textfield是第一个响应者。 This happens when I push a view controller on top of another view controller with an active text field. 当我将视图控制器推送到具有活动文本字段的另一个视图控制器之上时,会发生这种情况。 The keyboard goes away (as expected). 键盘消失(正如预期的那样)。 But if I bring the keyboard back by touching a textfield in the 2nd view controller, subsequent calls to resignFirstResponder have no effect. 但是,如果我通过触摸第二个视图控制器中的文本字段将键盘带回,则后续调用resignFirstResponder无效。

Here's simple code to reproduce the issue. 这是重现问题的简单代码。 This code is a view controller with a nav bar button to hide the keyboard, and another to push another copy of itself (with a confirmation UIAlertView). 此代码是一个视图控制器,带有一个用于隐藏键盘的导航栏按钮,另一个用于推送其自身的另一个副本(带有确认UIAlertView)。 The first copy works without problem. 第一个副本没有问题。 However, if you push a 2nd copy (when the first copy has a visible keyboard) it is impossible to dismiss the keyboard. 但是,如果您按第二个副本(当第一个副本具有可见键盘时),则无法关闭键盘。 This only happens if there is a UIAlertView (the confirmation) on the screen when the 2nd copy is pushed. 只有在按下第二个副本时屏幕上有UIAlertView(确认)时才会发生这种情况。 If you remove the #define ALERT line, everything works. 如果删除#define ALERT行,一切正常。

Does anyone know what is happening here? 有谁知道这里发生了什么? It looks like the UIALertView window is somehow interfering with the keyboard and keeping it's window from disappearing, which then confuses the next view. 看起来UialertView窗口在某种程度上干扰了键盘并使其窗口不再消失,从而混淆了下一个视图。 Is there any solution here other than pushing the 2nd view controller on a timer after the UIALertView is gone? 在UIALertView消失后,除了在计时器上按下第二个视图控制器之外,还有其他方法吗?

Sorry for the complex description. 对不起复杂的描述。 This is runnable code. 这是可运行的代码。 I hope that the code is clear. 我希望代码清楚。

@implementation DemoViewController

- (id) init {
    if (!(self = [super init])) 
        return nil;

    return self; 
}

- (void) dealloc {
    [_inputTextfield release];
    [super dealloc];
}

- (void) loadView {
    UIView *view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];

    _inputTextfield = [[UITextField alloc] initWithFrame:CGRectMake(0., 0., 320., 44.)];
    _inputTextfield.borderStyle = UITextBorderStyleRoundedRect;
    _inputTextfield.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
    _inputTextfield.keyboardAppearance = UIKeyboardAppearanceAlert;
    _inputTextfield.autocapitalizationType = UITextAutocapitalizationTypeNone;
    _inputTextfield.autocorrectionType = UITextAutocorrectionTypeNo;
    _inputTextfield.keyboardType = UIKeyboardTypeDefault;
    [view addSubview:_inputTextfield];

    self.view = view;
    [view release];
}

- (void) viewWillAppear:(BOOL) animated {
    [super viewWillAppear:animated];

    UIButton *downButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [downButton setTitle: @"keyboard down" forState:UIControlStateNormal];
    [downButton addTarget:self action:@selector(downButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    [downButton sizeToFit];    
    self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:downButton] autorelease];

    UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [nextButton setTitle: @"next" forState:UIControlStateNormal];
    [nextButton addTarget:self action:@selector(nextButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    [nextButton sizeToFit];
    self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithCustomView:nextButton] autorelease];;

}

- (void) viewWillDisappear:(BOOL) animated {
[super viewWillDisappear:animated];
    [_inputTextfield resignFirstResponder];
}

- (void) downButtonPressed:(id)sender {
    [_inputTextfield resignFirstResponder];
}

#define ALERT

- (void) alertView:(UIAlertView *) alertView didDismissWithButtonIndex:(NSInteger) buttonIndex {
    if (alertView.cancelButtonIndex == buttonIndex) {
        return; 
    }
    [self _nextButtonPressed];
}

- (void) _nextButtonPressed {
    DemoViewController *nextViewController = [[DemoViewController alloc] init];    
    [self.navigationController pushViewController:nextViewController];
    [nextViewController release];
}

- (void) nextButtonPressed:(id)sender {
#ifdef ALERT   
    UIAlertView *alert = [[UIAlertView alloc] init];
    alert.message = @"Next view?";  
    alert.cancelButtonIndex = [alert addButtonWithTitle:@"No"];
    [alert addButtonWithTitle:@"Yes"];
    alert.delegate = self;
    [alert show];
    [alert release];
#else   
    [self _nextButtonPressed];    
#endif
}

If you had bad luck resigning your first responders, here are a few solutions that might help: 如果你运气不好辞职你的第一响应者,这里有一些可能有帮助的解决方案:

  1. Determine who has remained the first responder after your last call to resign first responder. 确定在您最后一次呼叫辞职第一响应者后仍然是第一响应者的人。

  2. Try resigning all first responders by a single call to self.view (container view) 尝试通过一次调用self.view(容器视图)来辞职所有第一响应者

     [self.view endEditing:YES]; 
  3. ONLY if you've tried all the above methods and none worked, consider using this workaround. 只有在您尝试了上述所有方法且无法正常工作的情况下,请考虑使用此解决方法。

     -(BOOL)textViewShouldEndEditing:(UITextView *)textView { NSArray *wins = [[UIApplication sharedApplication] windows]; if ([wins count] > 1) { UIWindow *keyboardWindow = [wins objectAtIndex:1]; keyboardWindow.hidden = YES; } return YES; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM