一、问题背景
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实现中通过setEditing或resignFirstResponder结束编辑并收起键盘
三、H5侧问题
H5侧键盘ToolBar由系统提供,并没有提供相关API,所以会麻烦一些。主要通过监听系统提供的键盘通知UIKeyboardWillShowNotification和UIKeyboardDidShowNotification,从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];
}
至于该问题的根本原因暂未可知,欢迎各位大佬讨论