Search code examples
swiftxcodeuibuttontvos

How to remove focus from UIButton after Timer has expired (tvOS)


I'm setting up a simple tvOS application with a menu dock (Stack view containing buttons) at the bottom. After 5 seconds of inactivity I want the dock to hide (move down, out of view) and remove the focus from the currently focused button. The dock should reappear and re-focus on remote control activity. With the following code the dock hides, but just once, after the app has launched. Any help would be much appreciated!

@IBOutlet weak var menuDock: UIStackView!

var timer = Timer()

func resetTimer() {
    timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(ViewController.hideDock), userInfo: nil, repeats: true)
    let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.showDock))
    self.view.addGestureRecognizer(tapRecognizer)
}

@objc func hideDock() {
    UIView.animate(withDuration: 0.5, animations: {
        self.menuDock.frame.origin.y += 240
    }, completion: nil)
    timer.invalidate()
}

@objc func showDock() {
    UIView.animate(withDuration: 0.5, animations: {
        self.menuDock.frame.origin.y -= 240
    }, completion: nil)
    timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(ViewController.hideDock), userInfo: nil, repeats: true)
    timer.invalidate()
}

Solution

  • @IBOutlet weak var menuDock: UIStackView!
    
    var timer = Timer()
    
    func resetTimer() {
        timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(ViewController.hideDock), userInfo: nil, repeats: true)
        let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.showDock))
        self.view.addGestureRecognizer(tapRecognizer)
      }
    
      @objc func hideDock() {
        UIView.animate(withDuration: 0.5, animations: {
          self.menuDock.frame.origin.y += 240
          self.menuDock.arrangedSubviews.forEach{
            ($0 as? UIButton)?.isEnabled = false
          }
          self.setNeedsFocusUpdate()
          self.updateFocusIfNeeded()
        }, completion: nil)
        timer.invalidate()
      }
    
      @objc func showDock() {
        UIView.animate(withDuration: 0.5, animations: {
          self.menuDock.frame.origin.y -= 240
          self.menuDock.arrangedSubviews.forEach{
            ($0 as? UIButton)?.isEnabled = true
          }
          self.setNeedsFocusUpdate()
          self.updateFocusIfNeeded()
        }, completion: nil)
        timer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(ViewController.hideDock), userInfo: nil, repeats: true)
        timer.invalidate()
      }