我希望将所有ViewControllers中的方向锁定为纵向,除了其中一个,当它始终被推送到landscapeRight时。
我尝试了很多解决方案,使用UINavigationController
的扩展名,覆盖supportedInterfaceOrientations
和shouldAutorotate
,但没有运气。
答案 0 :(得分:2)
我找到了解决方案,现在它正在运行。
在每个视图控制器上,您应该将此代码仅用于支持所需的旋转(示例中为landscapeRight):
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.landscapeRight
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .landscapeRight
}
另一方面实现相同的方法但纵向方向。
为UINavigationController
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return (self.topViewController?.supportedInterfaceOrientations)!
}
open override var shouldAutorotate: Bool {
return true
}
注意:同样在Project的目标中启用所有需要的支持 取向。
我希望以横向模式显示的唯一一个控制器我以模态方式呈现。
答案 1 :(得分:1)
如果您使用导航控制器来呈现视图,您将会感到困惑。例如,我们通常通过调用performSegueWithIdentifier:sender:
或pushViewController:animated:
等导航控制器实例函数来利用导航控制器来处理添加视图。
推送不会像你想要的那样起作用。
segues也可能不起作用,特别是如果在IB中你创建了离开导航控制器的segue!
无论如何,如果你以某种方式成功地覆盖了父母"导航控制器的方向,您可能会遇到边缘情况,您可能正在使用粗略的东西,可能会失去对任何更新的支持。
那就是说,我找到的解决方法是:
第1步
使用presentViewController:animated:completion:
呈现landscapeRight视图控制器:
// assuming you're using IB and Main bundle
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let landscapeViewController = storyboard.instantiateViewController(withIdentifier: "LandscapeViewControllerStoryboardID")
self.present(landscapeViewController, animated: true, completion: {
print("landscapeViewController presented")
})
第2步
将以下覆盖添加到landscapeViewController
实际上现在可以正常工作:
/* override the preferredInterfaceOrientationForPresentation for a view controller
that is intended to be presented full screen in a specific orientation.
https://developer.apple.com/reference/uikit/uiviewcontroller */
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .landscapeRight
}
第3步(可选)
有了这一切,当你解雇你的landscapeViewController
时,仍然会有一些奇怪现象:它现在也是横向的。
这是因为导航控制器玩得很好。换句话说,现在导航控制器试图强制改变方向,强制它回到。
要执行此操作,您需要在<{em> present
landscapeViewController
之前存储设备的方向。在您从中显示landscapeViewController
的视图控制器中,我将其存储在实例变量中:
let ratio = self.view.bounds.width / self.view.bounds.height
if (ratio > 1) { // horizontal/landscape
self.currentOrientationIsPortrait = false // read by navigation controller when dismissing full screen view player
} else {
self.currentOrientationIsPortrait = true // read by navigation controller when dismissing full screen view player
}
然后,我在我的navigationController类中测试该视图控制器实例的值&#39;首选方向覆盖。让我们说我提出landscapeViewController
的视图控制器称为presentingViewController
:
// execution order: during visibileViewController's dismissal
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
get {
if visibleViewController != nil {
// check if landscapeViewController is being dismissed
if (visibleViewController as? LandscapeViewController) != nil {
// check if the top view controller is one that tracks its orientation (currently only presentingViewController)
if let presentingViewController = self.viewControllers.last as? PresentingViewController {
if presentingViewController.currentOrientationIsPortrait {
return .portrait // TODO should we not support portraitUpsideDown?
}
}
}
// otherwise, return whatever
return visibleViewController!.preferredInterfaceOrientationForPresentation
}
// otherwise, return whatever
return super.preferredInterfaceOrientationForPresentation
}
}
而宾果游戏。 (希望)
修改强>
另外,请不要忘记将此代码放在其他ViewControllers中:
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .portrait
}