UIWindow的一个兼容性问题

最近发现了一个奇怪的 UIWindow 的兼容性问题,通过一种比较取巧的方式解决了,如果你有更好的解决办法,请在回复中告诉我。

问题

描述

如果应用中使用了额外的 UIWindow,并且此 UIWindow 中包含了 UIWebView,那么在iOS 5.1或者以下的系统版本中,可能会出现在 UIWebView中触发键盘时,键盘处于不可见的状态

前提

  • 项目中使用了另一个 UIWindow (在这里给这个额外的 UIWindow 取个代号:HighLevelWindow)
  • 设置此 HighLevelWindow 的 windowLevel 大于 UIWindowLevelNormal,确保在显示时能覆盖在应用默认的 UIWindow 上面 (UIWindowLevelNormal 级别为应用默认的 UIWindow 的 windowLevel 取值)
  • HighLevelWindow 中的 rootViewController 里面包含了一个 UIWebView
  • 在显示此 HighLevelWindow 时,已经调用makeKeyAndVisible方法将 HighLevelWindow 设置成应用的keyWindow,确保能正常的接收到触摸事件

重现步骤

  1. 使用 iOS 5.1或者以下版本的设备运行应用,在应用默认的 UIWindow 中触发过键盘,如触发过一个输入框(UITextField),见下图:

在默认UIWindow中触发键盘

2.调出 HighLevelWindow,将 HighLevelWindow 中的 UIWebView 载入 google.com,点击 google 的搜索输入框,会发现网页虽然上推了,但是键盘处于不可见的状态,见下图:

键盘处于不可见的状态

分析

上 google 搜了很久,给出的解决方案都是说没把 HighLevelWindow 设置成应用的 KeyWindow,导致接收不到屏幕的触摸事件,但是从 google 网页上推可以看出,其实 HighLevelWindow 是可以接收到触摸事件的,而且我已经确定把 HightLevelWindow 设置成应用的 KeyWindow 了。

现在的症状就是键盘在默认的 UIWindow 中触发过后,在 HinhLevelWindow 中再次触发,键盘其实是被挡在了 HighLevelWindow 后面,处于不可见,不可点击的状态。(此症状可通过将 HighLevelWindow 的 frame.size 设置成只有屏幕一半大小来确定)

尝试了各种方法,都是不行的,而且从 iOS 6.0 开始,此 bug 是不存在的,那更可以确定是一个兼容性的问题了。

解决

我突然想起,就在之前项目还没改用 UIWebView 前,使用一般的 UITextField 输入框是可以正常的显示键盘的,于是,就有以下这种取巧的解决方案:
在包含了 UIWebView 的 UIViewController 显示时(viewDidAppear: 方法调用时),插入一个 UITextField,迅速的获取焦点,然后取消焦点,删除此 UITextFiled ,关键代码如下:

- FixedBugWindowViewController.m
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];

// 在系统版本低于 iOS 6.0 时才做此操作
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
{
// 新建一个 UITextField,并添加到视图中
UITextField *textFieldFixKeyBoardBug = [[UITextField alloc] initWithFrame:self.view.bounds];
[self.view addSubview:textFieldFixKeyBoardBug];

// 获取焦点,释放焦点
[textFieldFixKeyBoardBug becomeFirstResponder];
[textFieldFixKeyBoardBug resignFirstResponder];

// 将 UITextField 从视图中移除,并释放
[textFieldFixKeyBoardBug removeFromSuperview];
[textFieldFixKeyBoardBug release];
}
}

加上以上代码后,可以正常的显示键盘了。

可正常显示键盘

不单单是UIWebView,不单单是键盘

  • 不单单是 UIWebView,我在使用 MFMessageComposeViewController 时也遇过这个问题,类似的 MFMailComposeViewController 应该也会出现这个问题,可以使用相同的方法修复
  • 不单单是键盘,在 UIWebView 中,页面有一个下拉框,会显示一个 UIPickerView,此 UIPickerView 也处于被隐藏,不可见的状态,也可以使用此方法修复

Demo源码

Demo源码地址:https://github.com/zhenby/UIWindowKeyboardBug