Objective c 按下遥控器上的菜单按钮时,苹果电视应用程序未从初始视图控制器退出到主屏幕

Objective c 按下遥控器上的菜单按钮时,苹果电视应用程序未从初始视图控制器退出到主屏幕,objective-c,tvos,apple-tv,siri-remote,Objective C,Tvos,Apple Tv,Siri Remote,我刚刚有一个苹果电视应用程序因为 此外,Siri Remote上的菜单按钮在应用程序中的行为与预期不符。 具体来说,当用户启动应用程序并点击Siri遥控器上的菜单按钮时,应用程序不会退出苹果电视主屏幕 我正在查找这个,从我可以看出,这应该是在初始视图控制器上按下菜单按钮时的自动行为。但是,我有一个带有根视图控制器的导航控制器,通过脚本自动实例化,没有覆盖任何方法,当我按下此视图控制器上的菜单按钮时,不会发生任何事情 -(void)pressesBegan/Ended:(NSSet*)presse

我刚刚有一个苹果电视应用程序因为

此外,Siri Remote上的菜单按钮在应用程序中的行为与预期不符。 具体来说,当用户启动应用程序并点击Siri遥控器上的菜单按钮时,应用程序不会退出苹果电视主屏幕

我正在查找这个,从我可以看出,这应该是在初始视图控制器上按下菜单按钮时的自动行为。但是,我有一个带有根视图控制器的导航控制器,通过脚本自动实例化,没有覆盖任何方法,当我按下此视图控制器上的菜单按钮时,不会发生任何事情

-(void)pressesBegan/Ended:(NSSet*)presses withEvent:(UIPressesEvent *)event {
    if( presses.anyObject.type == UIPressTypeMenu) {
        if ( !somePopoverDisplayed) {
                // Let the sdk do its thing with the menu button 
            [super pressesBegan:presses withEvent:event];
        } else {
            // otherwise handle the menu button yourself ...
        }
        return;
    }

    // handle other buttons
}
有人能告诉我我是否遗漏了什么,或者是否有一种手动实现的方法吗


我想我可以截取菜单按钮并调用退出(0),但这似乎不是一种优雅的退出方式

我也因为这个原因拒绝了一个应用程序。在我的例子中,问题是覆盖
pressd:withEvent
方法组,而不调用
super
实现

所以我改变了这个:

-(void)pressesBegan:(NSSet*)presses withEvent:(UIPressesEvent *)event {
    // my code
}
为此:

-(BOOL)ignoreMenu:(NSSet*)presses {
    return ((UIPress *)[presses anyObject]).type == UIPressTypeMenu;
}

-(void)pressesBegan:(NSSet*)presses withEvent:(UIPressesEvent *)event {
    if ([self ignoreMenu:presses]) return [super pressesBegan:presses withEvent:event];
    // my code
}

菜单按钮又开始工作了。让人困惑的是,无论您是否调用
超级
,Home按钮都会继续工作。

所以我不情愿地这样调用exit(0)

-(无效)按开始:(NSSet*)按withEvent:(UIPresseEvent*)事件
{
[超级按开始:按事件:事件];
如果(按.anyObject.type==UIPressTypeMenu)
{
出口(0);
}
}

它不像自动工作时那么整洁;您最终会看到一个模糊的白色视图,持续约半秒,而不是更优雅的淡出动画。不过它确实有效,我可以确认我是通过苹果公司的审查程序这样做的。

更通用的方式是,只有在某些情况下,菜单按钮才会带你到主屏幕,第一个是当你启动应用程序并单击菜单按钮时,然后在你的应用程序中,如果你是在应用程序的“根视图”中

如果您在屏幕上显示一些内容,例如popover/对话框,它不由标准sdk控制,而是由您自己控制(即添加UIView作为popover),那么菜单按钮应该像在导航控制器上一样充当“取消/返回”

-(void)pressesBegan/Ended:(NSSet*)presses withEvent:(UIPressesEvent *)event {
    if( presses.anyObject.type == UIPressTypeMenu) {
        if ( !somePopoverDisplayed) {
                // Let the sdk do its thing with the menu button 
            [super pressesBegan:presses withEvent:event];
        } else {
            // otherwise handle the menu button yourself ...
        }
        return;
    }

    // handle other buttons
}

以下是最终为我工作的代码片段:

-(void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
    if( presses.anyObject.type == UIPressTypeMenu) {
        if (scene.view.paused == YES) {
            // This will return to the Apple TV Menu           
        } else {
            // This allows your code to run without exiting the app
            [self pauseScene];
            [super pressesBegan:presses withEvent:event];
        }
        return;
    }
}
-(void)按SENDED:(NSSet*)按withEvent:(UIPressesEvent*)事件{
如果(按.anyObject.type==UIPressTypeMenu){
如果(scene.view.paused==是){
//这将返回到Apple TV菜单
}否则{
//这允许您的代码在不退出应用程序的情况下运行
[自我暂停];
[超级按开始:按事件:事件];
}
返回;
}
}

当你不再需要手势识别器时,我只需要从你的视图中删除它(用于菜单按钮)

然后,如果您希望菜单按钮返回到上一个屏幕,然后只需再次添加手势识别器


这样,菜单按钮就可以正常工作,而无需调用exit()或强制应用程序以其他方式退出。

我从tvOS 9.1开始的完整工作代码(在Objective-C++下编译)


如果你在一个空的应用程序中看到这种行为,比如你描述的故事板设置,你可能发现了一个bug。(如果不是的话,就开始分段工作,看看你的应用程序有什么不同。)是的,我很确定这是一个bug。我要提交一份错误报告。如果我创建了一个全新的视图控制器,上面没有任何内容,它就可以工作。如果我添加一些标签、按钮、图像视图和自定义字体(即使没有连接任何东西或使用我自己的子类),它会突然停止。如何在Swift中手动返回Apple TV主屏幕的示例:。这是一个对我有效的示例,但有一点不同。不管出于什么原因,调用[super PressesBegind…]方法使应用程序无法返回到apple tv菜单,因为你很幸运。上次我调用
exit()
时,它被拒绝了。苹果说你不能在应用程序中调用exit。别忘了在ViewController级别调用-ignoreMenu:from-pressedesended:如果你也要覆盖它,那么controllerUserInteractionEnabled也需要在ViewController级别设置为YES(对于目标C)或true(对于Swift),否则会将press事件传递给super,因为菜单键不起作用。
bool AppRespondedToBack = false;
-(void)pressesBegan:(NSSet*)presses withEvent:(UIPressesEvent *)event
{
    UIPress *UP = (UIPress *)presses.anyObject;
    if ( UP && UP.type == UIPressTypeMenu )
    {
        //OnBack should be where you handle the back operation in your app
        AppRespondedToBack = OnBack();
        if ( !AppRespondedToBack )
            // Let AppleTV return to the home screen
            [super pressesBegan:presses withEvent:event];
    }
    else
        [super pressesBegan:presses withEvent:event];
}
-(void)pressesEnded:(NSSet*)presses withEvent:(UIPressesEvent *)event
{
    UIPress *UP = (UIPress *)presses.anyObject;
    if ( UP && UP.type == UIPressTypeMenu )
    {
        if ( !AppRespondedToBack )
             // Let AppleTV return to the home screen
            [super pressesEnded:presses withEvent:event];
    }
    else
        [super pressesEnded:presses withEvent:event];
}