在iOS 8/9中根据设备方向更改ViewController

在iOS 8/9中,基于设备方向的两个视图控制器之间的首选方式是什么? 我想要构build一个横向显示的乐器。 在肖像我想显示应用程序的设置。

在AppDelegate.swift里面的“didFinishLaunchingWithOptions”函数中我把:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "rotated", name: UIDeviceOrientationDidChangeNotification, object: nil) 

然后在AppDelegate类中放入以下函数:

 func rotated(){ if(UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation){ println("landscape") } if(UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation)){ println("Portrait") } } 

或者你可以使用这个:

 override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { if UIDevice.currentDevice().orientation.isLandscape.boolValue { println("landscape") } else { println("portraight") } } 

这是我为iOS 9创build的机制,但是这也适用于iOS 8。

 import UIKit extension CGSize { static func minMaxSize(size: CGSize) -> CGSize { return CGSize(width: size.minValue(), height: size.maxValue()) } static func maxMinSize(size: CGSize) -> CGSize { return CGSize(width: size.maxValue(), height: size.minValue()) } func minValue() -> CGFloat { return min(self.width, self.height) } func maxValue() -> CGFloat { return max(self.width, self.height) } } extension UIScreen { func isPortrait() -> Bool { return self.bounds.width < self.bounds.height } } class BaseViewController: UIViewController { var horizontalConstraints = [NSLayoutConstraint]() var verticalConstraints = [NSLayoutConstraint]() private lazy var _isPortrait: Bool = UIScreen.mainScreen().isPortrait() func isPortrait() -> Bool { if let parentViewController = self.parentViewController as? BaseViewController { return parentViewController.isPortrait() } return _isPortrait } override func loadView() { self.view = UIView() } override func viewDidLoad() { super.viewDidLoad() self.addViewController() self.addLayoutGuides() self.setupLayoutGuides() self.addSubViews() self.setupSubViews() } func addViewController() { /* override point */ } func addLayoutGuides() { /* override point */ } func setupLayoutGuides() { /* override point */ } func addSubViews() { /* override point */ } func setupSubViews() { /* override point */ } private func applyConstraints() { self.willApplyConstraints() self.isPortrait() ? self.applyVerticalConstrains() : self.applyHorizontalConstrains() self.didApllyedConstraints() } func willApplyConstraints() { /* override point */ } func applyVerticalConstrains() { /* override point */ } func applyHorizontalConstrains() { /* override point */ } func didApllyedConstraints() { /* override point */ override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { if let superView = self.view.superview { if superView.isKindOfClass(UIWindow.self) && self.parentViewController == nil { if CGSize.minMaxSize(size) == CGSize.minMaxSize(UIScreen.mainScreen().bounds.size) { _isPortrait = size.width < size.height } } } super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) self.applyConstraints() } } 

至less我假设子viewController将永远不会触及inheritance的private _isPortrait ,因为它是lazy 。 只有rootViewController的顶层视图可以设置这个属性。 检查完成后调用super viewWillTransitionToSize函数。 因此,如果在rootViewController上设置了该值,则在调用viewWillTransitionToSize函数时,所有子viewController都将具有正确的值。 这是必须完成的,因为你不能依赖子viewController视图的大小,但是至less你可以相信你的rootViewController是全屏的。 希望能以某种方式帮助别人。

所以我的RootViewController现在可能看起来像这样。

 class RootViewController: BaseViewController { override func addViewController() { /* add child view controller here so they can receive callbacks */ } override func addSubViews() { /* add your subviews here in a way you like so you can play with AutoLayout as you wish */ } override func setupSubViews() { /* setup up your views here and always activate vertical constraints here */ /* because iOS will always initialize in portrait even if launched in landscape */ /* deactivate your horizontal constrains and put them inside the array */ /* add vertical constraints to the vertical array; other constraints can be active */ /* without the need to be added somewhere */ } override func willApplyConstraints() { /* deactivate all constrains */ NSLayoutConstraint.deactivateConstraints(self.verticalConstraints) NSLayoutConstraint.deactivateConstraints(self.horizontalConstraints) } override func applyVerticalConstrains() { NSLayoutConstraint.activateConstraints(self.verticalConstraints) } override func applyHorizontalConstrains() { NSLayoutConstraint.activateConstraints(self.horizontalConstraints) } override func didApllyedConstraints() { /* force layouting if needed */ self.view.layoutIfNeeded() } } 

更新(Xcode 7 – OS X 10.11.1testing版):对于iPadtesting,使用iPad 2或iPad Retina模拟器,因为Air 1/2与AutoLayout有关。 所有的模拟器都会产生这个消息: <CATransformLayer: 0x790af320> - changing property masksToBounds in transform-only layer, will have no effect