iOS release包H5与原生键盘“完成”按钮点击无法收起键盘,问题分析与解决方案

2,310 阅读2分钟

一、问题背景

1、工单反馈,线上用户原生输入框编辑结束点击“完成”无反应
2、经复现,仅在14Pro机型生产包上现该问题
3、查询记录,此前工单已反馈过类似问题且已标记修复,猜测为非release环境验收
4、通过排查TextView相关环境,确定问题出现在键盘ToolBar,原生ToolBar由 IQKeyBoardManager库提供,H5键盘ToolBar由系统提供。

二、原生侧问题

原生侧IQKeyBoradManager提供键盘ToolBar的相关隐藏,修改事件操作。

1、移除键盘ToolBar

处理该问题最简单最快速的方法,将键盘ToolBar移除。

单个ViewController禁用键盘ToolBar:

viewWillAppear中:
objectivec [[IQKeyboardManager sharedManager] setEnableAutoToolbar:NO];

全局禁用键盘ToolBar:

didFinishLaunchingWithOptions中:
objectivec [[IQKeyboardManager sharedManager] setEnableAutoToolbar:NO];

2、重写键盘ToolBar"完成"按钮点击事件

在需要保留键盘ToolBar的情况,可以重写键盘ToolBar的事件来确保其正常功能。
在需要重写的ViewController中:
引入头文件:
objectivec #import <IQUIView+IQKeyboardToolbar.h>
设置Selector:
[self.view.keyboardToolbar.doneBarButton setTarget:self action:@selector(xxx)];
xxx实现中通过setEditingresignFirstResponder结束编辑并收起键盘

三、H5侧问题

H5侧键盘ToolBar由系统提供,并没有提供相关API,所以会麻烦一些。主要通过监听系统提供的键盘通知UIKeyboardWillShowNotificationUIKeyboardDidShowNotification,从window遍历子视图找到键盘ToolBar并做隐藏或重写事件等处理。

1、移除键盘ToolBar

添加监听:

[[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(removeKeyboardTopBar:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(removeKeyboardTopBar:) name:UIKeyboardDidShowNotification object:nil];

监听事件,寻找并隐藏ToolBar:

- (void) removeKeyboardTopBar:(NSNotification*)notify{
    UIWindow *keyboardWindow = nil;
    __block UIView* toolBarContainer = nil;
    NSArray* windows = [[UIApplication sharedApplication] windows];
    for (UIWindow *possibleWindow in windows) {
        if (![[possibleWindow class] isEqual:[UIWindow class]]) {
            keyboardWindow = possibleWindow;
            break;
        }
    }
        for (UIView *possibleFormView in [keyboardWindow subviews])
        {
            if([[[UIDevice currentDevice] systemVersion] floatValue]>8){
                if([[possibleFormView description] hasPrefix:@"<UIInputSetContainerView"])
                {
                    for(int i = 0 ; i < [possibleFormView.subviews count] ; i++)
                    {
                        UIView* hostkeyboard = [possibleFormView.subviews objectAtIndex:i];
                        if([[hostkeyboard description] hasPrefix:@"<UIInputSetHostView"])
                        {
                            for (id temp in hostkeyboard.subviews)
                            {
                                if ([[temp description] hasPrefix:@"<UIWebFormAccessory"])
                                {
                                    UIView* currentToolBar = (UIView*)temp;
                                    currentToolBar.hidden = true;
                                    toolBarContainer = hostkeyboard;
                                }
                            }
                        }
                    }
                }
            }else{
            // 兼容ios 8
                if ([[possibleFormView description] rangeOfString:@"UIPeripheralHostView"].location != NSNotFound) {
                    for (UIView *subviewWhichIsPossibleFormView in [possibleFormView subviews]) {
                        if ([[subviewWhichIsPossibleFormView description] rangeOfString:@"UIWebFormAccessory"].location != NSNotFound) {
                            [subviewWhichIsPossibleFormView removeFromSuperview];
                        }
                    }
                }
            }

        }
    if(toolBarContainer){
        if([notify.name isEqualToString:@"UIKeyboardWillShowNotification"]){
            [toolBarContainer setHidden:YES];
        }else if([notify.name isEqualToString:@"UIKeyboardDidShowNotification"]){
            [toolBarContainer setHidden:NO];
        }
        dispatch_async(dispatch_get_main_queue(), ^(){
            toolBarContainer.frame = CGRectMake(toolBarContainer.frame.origin.x,toolBarContainer.frame.origin.y+44,toolBarContainer.frame.size.width,toolBarContainer.frame.size.height);
        });
    }

    keyboardWindow = nil;
}

2、重写键盘ToolBar"完成"按钮事件:

添加监听:

[[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(dealWithKeyboardTopBar:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(dealWithKeyboardTopBar:) name:UIKeyboardDidShowNotification object:nil];

监听事件,寻找ToolBar并重写"完成"BarItem事件:

- (void) dealWithKeyboardTopBar:(NSNotification*)notify{
    UIWindow *keyboardWindow = nil;
    __block UIView* toolBarContainer = nil;
    NSArray* windows = [[UIApplication sharedApplication] windows];
    for (UIWindow *possibleWindow in windows) {
        if (![[possibleWindow class] isEqual:[UIWindow class]]) {
            keyboardWindow = possibleWindow;
            break;
        }

    }
        for (UIView *possibleFormView in [keyboardWindow subviews])
        {
            if([[[UIDevice currentDevice] systemVersion] floatValue]>8){
                if([[possibleFormView description] hasPrefix:@"<UIInputSetContainerView"])
                {
                    for(int i = 0 ; i < [possibleFormView.subviews count] ; i++)
                    {
                        UIView* hostkeyboard = [possibleFormView.subviews objectAtIndex:i];
                        if([[hostkeyboard description] hasPrefix:@"<UIInputSetHostView"])
                        {
                            for (id temp in hostkeyboard.subviews)
                            {
                                if ([[temp description] hasPrefix:@"<UIWebFormAccessory"])
                                {
                                    for (UIView *view in [temp subviews]) {
                                        for (UIView *t in view.subviews) {
                                            if ([[t description] hasPrefix:@"<UIToolbar"]) {
                                                UIToolbar *barTool = (UIToolbar *)t;
                                                for (UIBarButtonItem *barItem in barTool.items) {
                                                    if ([[barItem description] containsString:@"action=done"]) {
                                                [barItem setTarget:self];                                                     [barItem setAction:@selector(didClickDone)];
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    if(toolBarContainer){
        if([notify.name isEqualToString:@"UIKeyboardWillShowNotification"]){
            [toolBarContainer setHidden:YES];
        }else if([notify.name isEqualToString:@"UIKeyboardDidShowNotification"]){
            [toolBarContainer setHidden:NO];
        }
        dispatch_async(dispatch_get_main_queue(), ^(){
            toolBarContainer.frame = CGRectMake(toolBarContainer.frame.origin.x,toolBarContainer.frame.origin.y+44,toolBarContainer.frame.size.width,toolBarContainer.frame.size.height);
        });
    }
    keyboardWindow = nil;

}

// 结束编辑并关闭键盘
- (void)didClickDone {
    [self.view endEditing:YES];
}

至于该问题的根本原因暂未可知,欢迎各位大佬讨论