Swift iOS - 如何在设备旋转时隐藏特定选项卡中的 tabBar 而不是其他选项卡

Swift iOS -How to hide tabBar in specific tab but not other tabs when device rotates

我的应用程序是基于选项卡的,并且只有纵向。在一个特定的视图控制器中,我有一个固定在场景顶部的 16x9 视图,它显示视频,就像 YouTube 在 .portrait 方向时所做的那样。也像 YoutTube 一样,我允许特定的 vc 旋转到 .landscapeRight.landscapeLeft 以全屏模式显示该视频。我调用 func canRotate() 来实现这一点,并且我在 AppDelegate 中实现了它的功能。其他选项卡的 None 或 vc 可以旋转。

在设备旋转时的 vc 视频中,我使用通知来确定方向,并且由于视频在 .landscapeRight.landscapeLeft 中全屏显示,我隐藏了标签栏。

我遇到的问题是,当我在不同的选项卡(例如 tab2 或 tab3)上时,当我旋转设备时,由于 VideoVC 内部发生的事情,tabBar 被隐藏了。另一个 tabs/vcs 不旋转,但 tabBar 在 .landscapeRight.landscapeLeft 方向

时消失

如何在设备旋转时让 tabBar 隐藏在 VideoVC 中而不隐藏在其他选项卡中?

在 tab0 内,这是 VideoVC:

NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: .UIDeviceOrientationDidChange, object: nil)

@objc func deviceOrientationDidChange(){

        switch UIDevice.current.orientation {

        case .landscapeRight:

            view.transform = transform.rotated(by: -CGFloat.pi / 2)
            tabBarController?.tabBar.isHidden = true

        case .landscapeLeft:

            view.transform = transform.rotated(by: CGFloat.pi / 2)
            tabBarController?.tabBar.isHidden = true

        case .portrait:

            view.transform = CGAffineTransform.identity
            tabBarController?.tabBar.isHidden = false

        default: break
        }
}

@objc func canRotate(){} // allows this vc to rotate

AppDelegate:

...if (rootViewController.responds(to: Selector(("canRotate")))) {
          // Unlock landscape view orientations for this view controller
          return .allButUpsideDown;
   }

我尝试使用 Notification 来禁止在其他选项卡中隐藏 tabBar,这些选项卡有 vcs 不能旋转,但它很奇怪。它防止 tabBar 在旋转时隐藏在 VideoVC 中,或者如果我在按下通知选项卡之前在 VideoVC 中旋转了视频,那么它仍然会在那里隐藏 tabBar。

通知VC:

@objc func deviceOrientationDidChange(){

        switch UIDevice.current.orientation {

        case .landscapeRight, .landscapeLeft, .portrait:
            tabBarController?.tabBar.isHidden = false    

        defaults: break
        }
}

带有 VideoVC .portrait(可以旋转)的 tab0:

tab0 with VideoVC .landscapeLeft(可以旋转):

带有 NotificationsVC .portrait 的 tab3(无法旋转):

带有 NotificationsVC .landscapeLeft 的 tab3(无法旋转,但 tabBar 被隐藏且不应该 - 这就是问题所在):

修复很简单(虽然花了几个小时才弄明白)。我所要做的就是检查 view.window != nil 并将通知选择器中的内容包装在其中。

if (self.view.window != nil) {
   // put the what's inside the notification's selector in here
}

问题是因为 VideoVC 和 NotificationsVC 都被实例化了,我用来检测方向变化的 Notification 正在检查 UIDevice 本身,无论 VideoVC 的视图是否可见。无论 vc 我在其中,它仍然会响应设备被告知在方向更改时使用标签栏执行的任何操作。

NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: .UIDeviceOrientationDidChange, object: nil)

@objc func deviceOrientationDidChange(){

        // no matter what vc I was in this was still running
        switch UIDevice.current.orientation {

        case .landscapeRight:

            view.transform = transform.rotated(by: -CGFloat.pi / 2)
            tabBarController?.tabBar.isHidden = true

        case .landscapeLeft:

            view.transform = transform.rotated(by: CGFloat.pi / 2)
            tabBarController?.tabBar.isHidden = true

        case .portrait:

            view.transform = CGAffineTransform.identity
            tabBarController?.tabBar.isHidden = false

        default: break
        }
}

修复方法是将 UIDevice.current.orientation switch 语句包装在 if (self.view.window != nil) {} 中,并且 NotifcationsVC 不再响应设备方向,因为 VideoVC window 不再可见。

代码:

@objc func deviceOrientationDidChange(){

    // use this to check if this view's window isn't nil
    if (self.view.window != nil) {

        switch UIDevice.current.orientation {

           case .landscapeRight:

            view.transform = transform.rotated(by: -CGFloat.pi / 2)
            tabBarController?.tabBar.isHidden = true

        case .landscapeLeft:

            view.transform = transform.rotated(by: CGFloat.pi / 2)
            tabBarController?.tabBar.isHidden = true

        case .portrait:

            view.transform = CGAffineTransform.identity
            tabBarController?.tabBar.isHidden = false

        default: break
        }
    }
}