在 iOS 8.3 for iPad 上关闭 UIAlertView 后键盘弹出

Posted

技术标签:

【中文标题】在 iOS 8.3 for iPad 上关闭 UIAlertView 后键盘弹出【英文标题】:Keyboard pops up after UIAlertView is dismissed on iOS 8.3 for iPad 【发布时间】:2015-05-08 17:09:33 【问题描述】:

随着最新的 ios 8.3 版本,我们的应用开始出现奇怪的行为。

完成文本字段编辑后,用户可以单击关闭按钮,该按钮会弹出UIAlertView。当用户在 alertview 中点击 discard 时,alertview 和 current view 将被关闭。但不知何故,在视图消失后键盘会出现,这对用户来说非常烦人。

经过一些调试,似乎在关闭视图之前用户访问的最后一个文本字段显示了键盘。我在很多地方尝试了各种方法来endEditing 用于当前视图(在显示UIAlertView 之前,单击UIAlertView 中的按钮后;我什至将焦点设置到视图的另一个UI 元素)。它没有解决问题。

但对于这个特定问题,我不确定这是一个常见问题还是我们需要解决的问题。在 iOS 8.3 之前一切正常。

我们了解到 UIAlertView 在 iOS 8 中已被弃用。我们开始迁移到 UIAlertController。但如果有任何解决方法,我们很乐意听到。

这里有一些代码 sn-p。

- (IBAction)closeTapped:(UIButton *)sender

    // try to resign first responder
    // [self.tfName resignFirstResponder];
    // [self.tfPosition resignFirstResponder];
    [self.view endEditing:YES];

    if(self.orderDetails.isOpen && self.orderItemChanged)
    
        UIAlertView* saveAlert = [[UIAlertView alloc] initWithTitle:@"Unsaved Changes"
                                                            message:@"Your changes have not been saved. Discard changes?"
                                                           delegate:self
                                                  cancelButtonTitle:@"Cancel"
                                                  otherButtonTitles:@"Save", @"Discard", nil];
        [saveAlert show];
    
    else
    
        [self close];
    


- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

    switch(buttonIndex)
    
        case 1: // Save
        
            [self save];
            break;
        
        case 2: // Discard
        
            [self close];
            break;
        
    


- (void)close
   
    [self.delegate dismissEditOrderItemVC];

【问题讨论】:

在显示警报视图之前,您是否尝试在文本字段上调用 ​​resignFirstResponder? 是的,我为所有文本字段做了 resignFirstResponder 并为当前视图做了 endEditing。似乎不起作用:( 您可能需要向我们展示代码才能进一步提供帮助。似乎解除警报视图正在触发视图控制器上的一些生命周期调用。 我在原始帖子中添加了一个代码 sn-p。谢谢。 Keyboard loses hiding ability "if I use a UIAlertView" 的可能重复项 【参考方案1】:

如果您的部署目标是 iOS 8+,请尝试UIAlertController

这是UIAlertView 的快速修复:当您的文本字段或文本视图退出第一响应者时,延迟显示警报视图的调用。

[self performSelector:@selector(showAlertView) withObject:nil afterDelay:0.6];

【讨论】:

为我工作。您选择使用 0.6 延迟的任何原因? @KeithAylwin 我随机拿起号码。您可以根据需要选择其他号码:)【参考方案2】:

如果有人对此感到困惑,我希望这会有所帮助:

if (NSClassFromString(@"UIAlertController")) 
    UIAlertController* alert = ...

else 
    UIAlertView* alert = ...

【讨论】:

不是根本检查UIAlertController是否可用的方式。如果类不存在,您应该使用 if (NSClassFromString(@"UIAlertController")) 而不是返回 nil。使用上述方法会导致您的应用在 iOS 7.1 或更早版本上崩溃。 当你投反对票时,请至少解释原因。简单地按下并不能帮助查看答案有什么问题,或者至少在编辑后还剩下什么。 我不同意在您编辑后 否决这个答案(这是针对@pkamb,而不是您@puzzler)。我对以前形式的答案投了反对票,但在编辑时我删除了这个投票。如果我已经在队列中进行了审核,我也不确定我是否会接受该编辑。 之前状态的答案似乎是“使用此代码编辑: 等待改用此代码”。我在前面编辑了读者被告知忽略的部分。如果我删除了太多内容,请随时添加到当前答案中,并接受我的道歉。 所以实际上当前形式的答案是正确的。这就是我需要知道的。谢谢两位的解释。【参考方案3】:

您需要更改 ios 8.3 的警报

首先把它放在你的视图中

#define IS_IOS8 [[UIDevice currentDevice].systemVersion floatValue] >= 8.0

然后

if (IS_IOS8) 

        UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:@"Unsaved Changes" message:@"Your changes have not been saved. Discard changes?" preferredStyle:UIAlertControllerStyleAlert];

        UIAlertAction *saveAction = [UIAlertAction
                                    actionWithTitle:@"Save"
                                    style:UIAlertActionStyleCancel
                                    handler:^(UIAlertAction *action)
                                    
                                        [self save];
                                    ];

        UIAlertAction *cancelAction = [UIAlertAction
                                   actionWithTitle:@"Cancel"
                                   style:UIAlertActionStyleCancel
                                   handler:^(UIAlertAction *action)
                                   
                                       [alertVC dismissViewControllerAnimated:YES completion:nil];
                                   ];


        UIAlertAction *discardAction = [UIAlertAction
                                   actionWithTitle:@"Discard"
                                   style:UIAlertActionStyleCancel
                                   handler:^(UIAlertAction *action)
                                   
                                       [alertVC dismissViewControllerAnimated:YES completion:nil];
                                   ];



        [alertVC addAction:saveAction];
        [alertVC addAction:cancelAction];
        [alertVC addAction:discardAction];
        [self.view.window.rootViewController presentViewController:alertVC animated:YES completion:nil];

这将对您有所帮助,因为它可以帮助我解决同样的问题。 以上代码兼容 ios 7 & 8

【讨论】:

最好使用 class/respondsToSelector: 检查而不是使用 iOS 版本号:***.com/questions/25111011/… 请勿调用 -[dismissViewControllerAnimated:completion:] 自行关闭。 UIAlertViewController 将在调用处理程序块之前或之后自行关闭。同时,直接访问alertVC会导致actionalertController之间的retain循环。不要问我为什么会意识到......【参考方案4】:

我也是,在关闭 UIAlertController 后弹出一个键盘(光标位于上次使用的 textView 中),这是一个非常简单的修复:

在构建和呈现 UIAlertController 之前,

使用 [_activeTextView resignFirstResponder];键盘将重新出现。 使用 [self.view endEditing:YES];键盘不会再次出现。

希望对你有帮助。

【讨论】:

此解决方案适用于 Swift 4。只是为了清楚起见:self.view.endEditing(true)【参考方案5】:

尝试使用以下代码。它适用于 iOS 8 及以下版本

if (IS_OS_8_OR_LATER) 
        UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];

        UIAlertAction *cancelAction = [UIAlertAction
                                     actionWithTitle:@"OK"
                                     style:UIAlertActionStyleCancel
                                     handler:^(UIAlertAction *action)
                                     

                                     ];
        [alertVC addAction:cancelAction];

        [[[[[UIApplication sharedApplication] windows] objectAtIndex:0] rootViewController] presentViewController:alertVC animated:YES completion:^

        ];
    
    else
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:msg delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
        [alert show];
    

【讨论】:

【参考方案6】:

如果文本字段是第一响应者,则在解除警报时会自动弹出键盘。确保第一响应者被正确解雇:

[textField resignFirstResponder]

记住:在表格或滚动视图中,有时字段必须在屏幕上可见才能正确关闭响应者。

如果没有处于活动状态的第一响应者,则在解除警报时不应出现键盘。

对于这个问题的特殊情况,我建议设置一个委托方法来监听“完成”按钮并在委托回调中退出第一响应者。

或者,在开始编辑时,您可以存储对当前活动文本字段的引用,然后在“clickedButtonAtIndex”方法中,如果活动文本字段仍处于活动状态,您可以将其退出。

【讨论】:

您能否提供一个如何正确执行此操作的示例。我在滚动视图中没有它,但键盘似乎经常弹出。 [textField resignFirstResponder]【参考方案7】:

我注意到 textField 键盘和 alertViews 的一些奇怪行为......也许可以创建一个名为 disableKeyboard 的布尔值并像这样使用它:

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField 

    if (disableKeyBoard) 

        disableKeyboard = NO;
        return NO;

     else 

        return YES;

    



- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex 

    disableKeyboard = YES;


这只是一种解决方法,并没有解决核心问题,无论它是什么。要使此方法起作用,您需要在标题中设置 alertView 和 textField 委托方法。

【讨论】:

textFieldShouldBeginEditing 在键盘闪烁时不会触发

以上是关于在 iOS 8.3 for iPad 上关闭 UIAlertView 后键盘弹出的主要内容,如果未能解决你的问题,请参考以下文章

使用 UI 自动化以编程方式打开/关闭真实 iOS 设备上的 wifi

UI设计类似于Android中的iOS [关闭]

在 iOS 8.3 中向 UIWindow 添加子视图

iOS 8.3 UIAlertController 在尝试添加文本字段时崩溃

在 iOS 8.3 中,UITabBarViewController 作为 UISplitViewController 的主控的问题

当设备连接由 iOS 8.3 供电时,设备在 Xcode 6.1 中不合格