设备物理方向
1 | typedef NS_ENUM(NSInteger, UIDeviceOrientation) { |
- 通过
[UIDevice currentDevice].orientation获取 - Readonly
- 当打开系统的锁屏开关时,值只为
UIDeviceOrientationPortrait
界面显示方向
1 | // Note that UIInterfaceOrientationLandscapeLeft is equal to UIDeviceOrientationLandscapeRight (and vice versa). |
- 通过
[UIApplication sharedApplication].statusBarOrientation获取 UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight:设备向右旋转,界面向左旋转
控制界面旋转方向
1. 配置
- 项目配置

- plist配置

2. AppDelegate设置
实现下面接口:
1 | func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { |
3. UIViewController设置
重写下面属性:
shouldAutorotateInterface方向是否跟随设备方向自动旋转,如果false,则后面两个方法不会掉用1
2
3override var shouldAutorotate: Bool {
return true
}supportedInterfaceOrientations返回支持的方向,iPhone默认值为1
2
3override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}UIInterfaceOrientationMaskAllButUpsideDown,iPad默认值为UIInterfaceOrientationMaskAllpreferredInterfaceOrientationForPresentation返回最优先显示的屏幕方向1
2
3override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .portrait
}
结果
UIViewController的方向为这三个设置的交集- 设置3仅在以下两种情况才会生效:
- 当前
viewController为window的rootViewController - 当前
viewController被presentModalViewController出来
- 当前
特殊VC的界面旋转方向
UINavigationController
当rootViewController为UINavigationController时,界面的旋转方向由UINavigationController控制而并非由push到里面的VC控制
- 网络上面提供的解决方案
继承UINavigationController,重写其三个方法1
2
3
4
5
6
7
8
9
10
11override var shouldAutorotate: Bool {
return self.topViewController?.shouldAutorotate ?? true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return self.topViewController?.supportedInterfaceOrientations ?? .portrait
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return self.topViewController?.preferredInterfaceOrientationForPresentation ?? .portrait
} - Apple提供的方案
实现UINavigationControllerDelegate1
2
3func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
return self.topViewController?.supportedInterfaceOrientations ?? .portrait
}
两种方案的原理实际上是一样的,但是实际展现的效果都有缺陷
例如,先往navigationController推一个只支持.landscape的viewController A,然后再推一个只支持.portrait的viewController B。这时候界面并不会在push B的时候立刻变成.portrait,需要旋转一下设备,触发一下系统的回调,才能跑到设置3的回调里面去。pop的时候亦是如此
目前的解决方案
1 | override func viewDidLoad() { |
强制旋转