Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent or detect events passed on from iOS 8 keyboard

In our iOS 8 app, the search screen, which is similar to the search screen of the App Store app, no longer works reliably. When a user taps a key, the keyboard is sometimes closed or even an action executed.

Part of the reason is that the tap event is passed on to lower layers, which is close the keyboard (smoke screen), navigate to a search result (UITableView with search result) or execute the search (UITableView with search term suggestions).

For some unknown reason, it properly works as long as the user stays in the app. However, if he/she goes to a different app and then returns, the events are passed on. This behavior affects all iOS 8 version (8.0.x, 8.1).

How can we prevent the keyboard from passing on tap events or how can we detect such an event (e.g. from tableView:didSelectRowAtIndexPath:)?

The question "Keyboard intermittently disappears when editing using IOS 8" seems to refer to the same problem though I can't figure out how to apply that ugly hack to my situation.


I've just found a similar post in Apple's developer forum. Unfortunately, it has no answers and has been archived in the mean time:

I have overriden -hitTest:withEvent: on a view on my view hierarchy where I check if it was touched and will forward the touch to its subviews and fire a selector to dismiss the keyboard.

On iOS 7 (and, more strangely, when the app is launched on iOS 8) this works perfectly and -hitTest:withEvent: will never be called if the view is behind the keyboard and the user taps on the keyboard.

But on iOS 8, if the user sends the app to the background and brings it back to the foreground, tapping anything on the keyboard will trigger -hitTest:withEvent: as if the view was above the keyboard on the view hierarchy. I've used Reveal.app to verify that it is not above the keyboard, it is behind as expected.

Anyone got any ideas of what could be happening? I've created a sample project and attached it to a radar for Apple as this looks like a bug on iOS 8 for not working the same way consistently.

Update

My search screen contains two views (on top of each other): a background view visible when no search results are available and a table view visible if search results are available. On top of these, I dynamically add two additional views if the search bar becomes active: a smoke class view that can be tapped to end the search text entry and a table view that displays search text suggestions. All four views are directly contained in the view controller's main view and cover the full area.

The interesting thing now is that the keyboard forwards event the two dynamically added views but not to the two lower views that are always there.

like image 758
Codo Avatar asked Oct 31 '22 15:10

Codo


1 Answers

I believe it's a bug that tap events are passed on to views underneath the keyboard. As I've figured out in the mean time that only the dynamically added views are affected and not the ones that are part of the Interface Builder file, I've now come up with a work around: if the keyboard appears, I shrink these two view so they do not extend underneath the keyboard. And I grow them again when the keyboard disappears.

So this is the code. The upper part up to (and excluding) [[NSNotificationCenter defaultCenter] has existed before. The rest is the workaround.

- (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;
}
like image 188
Codo Avatar answered Nov 15 '22 06:11

Codo