如documentation中所述
视图控制器可以覆盖supportedInterfaceOrientations 方法来限制支持的方向列表。
所以我们需要覆盖shouldAutorotate 和supportedInterfaceOrientation 来定位view controllers。
通常,系统仅在窗口的根视图控制器或呈现为填充整个屏幕的视图控制器上调用此方法。
如果您有非常简单的配置,例如您的目标 view controller 是 rootViewController 或 window 或被呈现为覆盖整个屏幕,这将起作用。
但是,当您有其他配置(例如 target view controller)嵌入到其他容器视图控制器(例如 UINavigationController 或 UITabBarController)中时,现在应用程序的窗口只会向其 rootViewController(现在为 container view controller)询问 @ 987654334@。
现在进一步阅读文档,
子视图控制器使用其父视图控制器为它们提供的窗口部分,不再直接参与有关支持哪些旋转的决策。
因此,这些容器视图控制器的默认实现可能不会向那里的孩子询问 supportedInterfaceOrientation 偏好。
所以为了让我们的目标child view controller 在那里指定supportedIntefaceOrientation,我们需要告诉那里的容器视图控制器这样做。
如果是UINavigationController
extension UINavigationController {
open override var shouldAutorotate: Bool {
return true
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return topViewController?.supportedInterfaceOrientations ?? .allButUpsideDown
}
}
万一还是UITabBarController
extension UITabBarController {
open override var shouldAutorotate: Bool {
return true
}
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return selectedViewController?.supportedInterfaceOrientations ?? .allButUpsideDown
}
}
编辑
要在视图控制器中实现正确的旋转行为,您应该将这些 ContainerViewController(UINavigationController、UITabBarController、UISplitViewController 等)子类化,然后覆盖这些属性,因为扩展这些UIKit 类全局 将导致Customizing Existing Classes 中提到的意外行为。
如果一个类别中声明的方法的名称与原始类中的方法名称相同,或者同一类(甚至超类)上的另一个类别中的方法名称相同,则行为未定义至哪个方法实现在运行时使用。如果您在自己的类中使用类别,这不太可能成为问题,但在使用类别向标准 Cocoa 或 Cocoa Touch 类添加方法时可能会导致问题。