Search code examples
swifttvosapple-tvgamepadsiri-remote

How to tell Siri Remote button presses and gamepad button presses apart?


I wrote an override for pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) on my ViewController.

  open override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
    #if os(tvOS)
    for press in presses {
      switch press.type {
      case .menu: print("menu"); break;
      case .select: print("select"); break;
      case .playPause: print("playPause"); break;
      default: break;
      }
    }
    #endif
  }

It correctly sees a UIPress that has press.type set to .menu when I press the “menu” button on the Siri Remote.

However, it also gets a .menu press event when I press “circle” (buttonB) on a DualShock 4 gamepad that I've connected to my Apple TV. Is this normal? Is it documented behavior? (I assume the idea is to make apps “automatically” navigable with a gamepad.)

I don't always want “B on the gamepad” and “MENU on the remote” to do the same thing. How can I tell these two cases apart? Neither UIPressesEvent nor UIPress seem to carry any information in their fields as to which device originated the keypress. Is there some other way?


Solution

  • I ended up changing my ViewController situation around so that I present a GCEventViewController whenever I don't want the B button to perform navigation. Then I use the tools offered by GameController to handle gamepad presses and pressesBegan seems to no longer be triggered by the B button.