uiviewcontrollertvosuitapgesturerecognizersiri-remote

tvOS - catch MENU button presses during push-view-controller transition


I have a UIViewController in my tvOS app which will only appear for a few seconds, and needs totally customizable MENU button handling. I create it like so:

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Add a tap gesture recognizer to handle MENU presses.
    UITapGestureRecognizer *tapGestureRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    tapGestureRec.allowedPressTypes = @[@(UIPressTypeMenu)];
    [self.view addGestureRecognizer:tapGestureRec];
}

- (void)handleTap:(UITapGestureRecognizer *)sender
{
    // Code to process the MENU button is here.
}

I display the view controller using pushViewController:animated::

UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
[self pushViewController:controller animated:isAnimated];

I've found that if the user presses MENU as soon as the screen starts to appear, while the cross-fade transition effect is still displaying, they are able to dodge the UITapGestureRecognizer and go back to a previous screen, which is not intended. They can also cause issues by mashing MENU over and over again--eventually they will escape out of things that they should not be able to.

How can I ensure that the MENU press always reaches my override? Is there a way to specify an app-encompassing MENU button handler and still use a UINavigationController?


Solution

  • A solution that worked for me was to install a UITapGestureRecognizer onto self.navigationController.view. Any taps which get missed by the regular UIViewControllers end up getting caught by the navigation controller's recognizer instead. If you install UITapGestureRecognizers on each view controller you create, the only taps which will fall through the cracks to the navigation controller are taps that occur mid-transition, and it is safe to just ignore those taps completely.

    Note that when you want MENU to go back to the home screen, you will need to temporarily remove this tap recognizer and let tvOS handle the tap on its own, as I could find no clean way to escape to the home screen in my code (short of exit(0)).