Atika
Atika

Reputation: 1618

Detect when a UIViewController has been dismissed by the remote's menu button in tvOS

I am working on a Apple TV app (tvOS) where the first view controller open a second view controller via a segue. When I choose an option on the second view controller it execute an unwind action on the first view controller.

My problem is when I press the remote menu button, the second view controller modal dismiss automatically and I find no way to execute an action on the first view controller or to be notified.

How can I detect when a controller opened via a segue has been dissmissed by the remote's menu button ?

┌─────────────┐               ┌─────────────┐   
│ First View  │    ┌─────┐    │ Modal View  ├──┐
│ Controller  ├────┤segue├────▶ Controller  │  │
└─────────────┘    └─────┘    └─────────────┘  │
                ┌────────────┐      ┌───────┐  │
                │ Modal Auto │      │ Menu  │  │
  Action ??  ◀──┤  Dismiss   ◀──────│Button │◀─┘
                └────────────┘      └───────┘   

Upvotes: 6

Views: 4322

Answers (3)

atulkhatri
atulkhatri

Reputation: 11333

This is the what worked for me using Swift 5:

private func setupRemoteGesture() {
    let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleMenuPress))
    tapRecognizer.allowedPressTypes = [NSNumber(value: UIPress.PressType.menu.rawValue)]
    view.addGestureRecognizer(tapRecognizer)
}

@objc private func handleMenuPress() {
    // Menu button pressed
}

Upvotes: 0

Atika
Atika

Reputation: 1618

First view controller:

@IBAction func modalDismissed(segue: UIStoryboardSegue) {
    print("Modal dismissed")
}

Modal view controller:

override func pressesBegan(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
    for item in presses {
        if item.type == .Menu {
            self.performSegueWithIdentifier("dismissModal", sender: nil)
        }
    }
    super.pressesBegan(presses, withEvent: event)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "dismissModal" {
        print("Modal Dismiss")
    }
}

Create an exit segue on modal view controller named "dismissModal" enter image description here

Upvotes: 0

earthtrip
earthtrip

Reputation: 508

I believe this is what you're trying to accomplish

// Put this in your FirstViewController
@IBAction func returnToFirstViewController(segue:UIStoryboardSegue) {
  print("This is called after  modal is dismissed by menu button on Siri Remote")
}

// Put this in your SecondViewController
override func viewDidLoad() {
  super.viewDidLoad()  

  // Do any additional setup after loading the view.

  let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("handleMenuPress:"))
  tapRecognizer.allowedPressTypes = [UIPressType.Menu.rawValue]
  view.addGestureRecognizer(tapRecognizer)
}

func handleMenuPress(recognizer: UITapGestureRecognizer) {
  self.performSegueWithIdentifier("YourUnwindSegueIdentifier", sender: nil)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
  if segue.identifier == "YourUnwindSegueIdentifier" {
     // do any cleanup activities here if you need
  }
}

Now you have to make some storyboard connections. Go into your SecondViewController and ctrl-drag from your Controller icon to your Exit icon and you'll see a drop down like this:

enter image description here

Select the method to connect it and then you'll see an Unwind Segue in your SecondViewController in the storyboard. Give that segue the identifier name of "YourUnwindSegueIdentifier" (so my sample code will work - or use whatever name you want). Build and run and this should get you what you need.

Upvotes: 1

Related Questions