tvOS - 在推送视图控制器转换期间捕获 MENU 按钮按下

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

我的 tvOS 应用程序中有一个 UIViewController,它只会出现几秒钟,并且需要完全可自定义的 MENU 按钮处理。我是这样创建的:

- (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.
}

我使用 pushViewController:animated::

显示视图控制器
UIViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:identifier];
[self pushViewController:controller animated:isAnimated];

我发现如果用户在屏幕开始出现时立即按下 MENU,同时交叉淡入淡出过渡效果仍在显示,他们能够躲避 UITapGestureRecognizer 并返回到上一个屏幕,这不是故意的。他们还可以通过一遍又一遍地混合 MENU 来引起问题——最终他们会逃脱他们不应该逃脱的事情。

我怎样才能确保按 MENU 总是达到我的覆盖?有没有办法指定包含应用程序的 MENU 按钮处理程序并仍然使用 UINavigationController?

对我有用的解决方案是在 self.navigationController.view 上安装 UITapGestureRecognizer。任何被常规 UIViewControllers 错过的点击最终都会被导航控制器的识别器捕获。如果你在你创建的每个视图控制器上安装 UITapGestureRecognizers,唯一会通过裂缝落到导航控制器的点击是在过渡过程中发生的点击,完全忽略这些点击是安全的。

请注意,当您希望 MENU 返回主屏幕时,您将需要暂时删除此点击识别器并让 tvOS 自行处理点击,因为我找不到干净的方式逃回主屏幕我的代码中的屏幕(exit(0) 的缩写)。

由于这种行为,我遇到了非常相似的问题。 在我的例子中,我有自定义焦点管理,这取决于在 pressesEnded 上检测到并由 preferredFocusedView 管理的 MENU 按钮单击。但是当导航控制器弹出 ViewController 并且此时用户第二次单击 MENU 按钮时,然后 UINavigationController class 检测到 pressesEnded 然后在我的上调用 preferredFocusedView目的地 ViewController 我的管理在哪里,但是 pressesEnded 不会被调用,因为 "stolen" 被 UINavigationController.

在我的例子中,这个问题的解决方案是创建 "dummy" class,UINavigationController 将像这样使用它:

class MenuPhysicalHackNavigationController: UINavigationController {

    override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {

    }

    override func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {

    }

    override func pressesCancelled(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {

    }

    override func pressesChanged(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {

    }

}