2025-06-07 iOS 横竖屏控制方法及优先级梳理

1. 基础概念

iOS 屏幕方向的控制,主要通过三部分控制:

Info.plist 中配置全局支持的屏幕方向

AppDelegate 提供的 application:supportedInterfaceOrientationsForWindow: 方法

各个 UIViewController 及其容器控制器的相关旋转方法

2. Info.plist 中的方向配置

UISupportedInterfaceOrientations (iPhone) 和 UISupportedInterfaceOrientations~ipad (iPad)

这里声明 app 支持哪些方向,比如只支持竖屏(Portrait),或者支持竖屏和横屏(Portrait + LandscapeLeft + LandscapeRight)

这是全局限制,决定整个应用可支持的方向范围,任何代码都不能超出这里的限制。

3. AppDelegate 中的方法

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window

该方法优先级高于 Info.plist 的配置,可以动态控制整个 app 支持的方向。

如果实现了此方法,系统会调用它来决定支持的方向,默认返回 Info.plist 的配置。

如果想针对某个窗口或者某些情况特殊处理,可以在这里实现。

4. UIViewController 相关方法

这些方法决定单个控制器是否支持旋转及支持的方向范围:

- (BOOL)shouldAutorotate

返回是否允许自动旋转,返回 NO 会禁止旋转。

- (UIInterfaceOrientationMask)supportedInterfaceOrientations

返回支持的屏幕方向掩码(如:UIInterfaceOrientationMaskPortrait)

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation

当控制器以模态形式展示时,初始方向。

5. 容器控制器的处理

5.1 UINavigationController

系统默认 优先使用 UINavigationController 自己的旋转方法,而不是它的子控制器。

UINavigationController 的默认实现:

shouldAutorotate 返回 YES

supportedInterfaceOrientations 返回所有方向(通常是全支持)

开发者需要重写 UINavigationController 的这些方法,将调用转发给它的 topViewController(当前显示的控制器),示例:

- (BOOL)shouldAutorotate {
    return [self.topViewController shouldAutorotate];
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return [self.topViewController supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [self.topViewController preferredInterfaceOrientationForPresentation];
}

5.2 UITabBarController

规则与 UINavigationController 类似,默认只返回所有方向支持。

同样推荐重写上述三个方法,将权限转发给当前选中的子控制器:

- (BOOL)shouldAutorotate {
    return [self.selectedViewController shouldAutorotate];
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return [self.selectedViewController supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}

6. 调用顺序及优先级总结

系统判断屏幕方向时先参考 Info.plist,如果不支持,方向直接被限制;

如果实现了 AppDelegate 的 application:supportedInterfaceOrientationsForWindow:,系统会调用该方法返回方向掩码,覆盖 Info.plist 的配置;

系统询问当前显示的顶层控制器是否允许旋转:

如果是容器控制器(UINavigationController、UITabBarController),默认它们自己的实现优先级高于子控制器。

但容器控制器默认实现支持所有方向,通常不符合需求。

你应该重写容器控制器的相关方法,将调用转发给子控制器。

子控制器的 shouldAutorotate 和 supportedInterfaceOrientations 生效,决定是否旋转和支持哪些方向;

模态弹出控制器展示时会调用 preferredInterfaceOrientationForPresentation 来确定初始方向;

7. 注意点

只要 shouldAutorotate 返回 NO,系统不会旋转屏幕;

supportedInterfaceOrientations 是一个位掩码,允许多个方向,比如:

UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft

如果 app 是使用模态视图弹出控制器,要确保模态控制器的方向方法正确,否则可能导致旋转异常;

旋转行为仅对设备物理旋转生效,不会影响通过代码设置旋转方向(例如使用私有 API 强制方向)。

8. 总结示意图

用户旋转设备
      ↓
系统查询 Info.plist 支持的方向范围
      ↓
系统调用 AppDelegate application:supportedInterfaceOrientationsForWindow:(如果实现)
      ↓
系统询问最上层控制器(如 UINavigationController 或 UITabBarController)
      ↓
容器控制器的 shouldAutorotate & supportedInterfaceOrientations
      ↓
容器控制器(如 UINavigationController)是否转发给子控制器
      ↓
子控制器的 shouldAutorotate & supportedInterfaceOrientations
      ↓
确定是否旋转,旋转到哪个方向
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容