防止或检测从iOS 8键盘传递的事件

Cod*_*odo 5 keyboard-events ios ios8

在我们的iOS 8应用程序中,搜索屏幕与App Store应用程序的搜索屏幕类似,不再可靠.当用户轻敲键时,键盘有时会关闭甚至执行操作.

部分原因是tap事件被传递到较低层,即关闭键盘(烟雾屏幕),导航到搜索结果(带搜索结果的UITableView)或执行搜索(带搜索术语建议的UITableView).

由于某些未知原因,只要用户留在应用程序中,它就能正常工作.但是,如果他/她转到另一个应用程序然后返回,则会传递事件.此行为会影响所有iOS 8版本(8.0.x,8.1).

我们如何防止键盘传递点击事件或我们如何检测这样的事件(例如来自tableView:didSelectRowAtIndexPath:)?

使用IOS 8编辑时 " 键盘间歇性消失 "的问题似乎引用了同样的问题,虽然我无法弄清楚如何将这种丑陋的黑客应用于我的情况.


我刚刚在Apple的开发者论坛上找到了类似的帖子.不幸的是,它没有答案,并在同一时间存档:

我在视图层次结构上的视图上覆盖-hitTest:withEvent:我检查它是否被触摸并将触摸转发到其子视图并触发选择器以关闭键盘.

在iOS 7上(更奇怪的是,当应用程序在iOS 8上启动时)这非常有效,并且-hitTest:withEvent:如果视图位于键盘后面且用户点击键盘,则永远不会调用它.

但是在iOS 8上,如果用户将应用程序发送到后台并将其带回前台,则点击键盘上的任何内容都会触发-hitTest:withEvent:就好像视图位于视图层次结构上的键盘上方一样.我已经使用Reveal.app验证它不在键盘上方,它按预期落后.

任何人都对可能发生的事情有任何想法?我已经创建了一个示例项目并将其附加到Apple的雷达上,因为这看起来像iOS 8上的一个错误,因为它不能以相同的方式一致地工作.

更新

我的搜索屏幕包含两个视图(彼此叠加):没有搜索结果时可见的背景视图,如果搜索结果可用,则可以看到表格视图.除此之外,如果搜索栏变为活动状态,我会动态添加两个额外的视图:可以点击以结束搜索文本条目的烟雾类视图和显示搜索文本建议的表视图.所有四个视图都直接包含在视图控制器的主视图中,并覆盖整个区域.

现在有趣的是,键盘转发事件是两个动态添加的视图,但不是两个始终存在的低视图.

Cod*_*odo 2

我认为点击事件传递到键盘下方的视图是一个错误。正如我同时发现的,只有动态添加的视图受到影响,而不是 Interface Builder 文件中的视图,我现在想出了一个解决方法:如果键盘出现,我会缩小这些视图两个视图,这样它们就不会延伸到键盘下方。当键盘消失时,我会再次长出它们。

这就是代码。上半部分之前[[NSNotificationCenter defaultCenter]已经存在(并且不包括)。剩下的就是解决方法了。

- (BOOL) searchBarShouldBeginEditing: (UISearchBar*) searchBar {

    // calculate from for entire area
    CGRect frame = ...  // omitted

    // add smoke screen
    _smokeScreen = [UIButton buttonWithType: UIButtonTypeCustom];
    _smokeScreen.frame = frame;
    _smokeScreen.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    _smokeScreen.backgroundColor = [UIColor colorWithWhite: 0.0f alpha: 0.5f];
    [_smokeScreen addTarget: self action: @selector(smokeScreenPressed:) forControlEvents: UIControlEventTouchDown];
    [self.view addSubview: _smokeScreen];

    // add table view for search term suggestions
    _suggestionTableView = [[SearchControllerTableView alloc] initWithFrame:frame style:UITableViewStylePlain];
    _suggestionTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    _suggestionTableView.dataSource = self;
    _suggestionTableView.delegate = self;
    _suggestionTableView.searchController = self;
    _suggestionTableView.hidden = YES;
    [self.view addSubview:_suggestionTableView];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:)
                                                 name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification object:nil];

    return YES;
}


- (void) keyboardDidShow:(NSNotification *) notification
{
    // shrink the smoke screen area and the table view because otherwise they'll receive tap events from the keyboard
    CGRect screenRect = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGRect windowRect = [self.view.window convertRect:screenRect fromWindow:nil];
    CGRect viewRect = [self.view convertRect:windowRect fromView:nil];

    [self setBottom: viewRect.origin.y];
}


- (void) keyboardWillHide:(NSNotification *) notification
{
    // grow the views again
    [self setBottom: self.view.frame.size.height];
}


- (void) setBottom: (CGFloat)y
{
    CGRect frame = _suggestionTableView.frame;
    frame.size.height = y - frame.origin.y;
    _suggestionTableView.frame = frame;

    frame = _smokeScreen.frame;
    frame.size.height = y - frame.origin.y;
    _smokeScreen.frame = frame;
}
Run Code Online (Sandbox Code Playgroud)