iOS开发:如何让模态呈现的ViewController可旋转,呈现者固定竖屏?
实现模态ViewController可旋转、发起ViewController保持固定方向的方案
你当前通过AppDelegate全局控制方向锁的思路是可行的,要实现模态页单独旋转的需求,只需要在模态呈现前后动态调整全局方向锁,再结合ViewController自身的旋转权限配置即可,具体步骤如下:
1. 完善OrientationManager工具类
先把你的OrientationManager补全,方便全局统一控制方向锁:
struct OrientationManager { static func lockOrientation(_ orientation: UIInterfaceOrientationMask) { guard let delegate = UIApplication.shared.delegate as? AppDelegate else { return } delegate.orientationLock = orientation } // 可选方法:强制刷新当前屏幕方向,确保设置立即生效 static func forceOrientationRefresh() { UIViewController.attemptRotationToDeviceOrientation() } }
2. 在发起呈现的ViewController中做状态切换
在弹出模态页的ViewController里,呈现前解锁允许旋转的方向,模态页消失后恢复竖屏锁定:
class PresentingViewController: UIViewController { // 示例:点击按钮弹出模态页 @IBAction func showModalVC(_ sender: UIButton) { let modalVC = ModalViewController() // 呈现前允许模态页支持的方向(比如除了倒过来的所有方向) OrientationManager.lockOrientation(.allButUpsideDown) present(modalVC, animated: true) // 监听模态页消失事件,用于恢复方向锁 modalVC.presentationController?.delegate = self } } // 实现UIAdaptivePresentationControllerDelegate处理消失逻辑 extension PresentingViewController: UIAdaptivePresentationControllerDelegate { func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { // 模态页关闭后,恢复竖屏锁定 OrientationManager.lockOrientation(.portrait) OrientationManager.forceOrientationRefresh() } }
3. 配置模态ViewController的旋转权限
在你的模态ViewController里,明确声明它支持的旋转方向,让系统知道它可以响应旋转:
class ModalViewController: UIViewController { override var supportedInterfaceOrientations: UIInterfaceOrientationMask { // 这里设置你允许的方向,比如.allButUpsideDown或者仅横屏.landscape return .allButUpsideDown } override var shouldAutorotate: Bool { return true } }
4. 容器类适配(可选)
如果你的项目用了UINavigationController或UITabBarController这类容器,需要给它们添加扩展,让它们转发子ViewController的旋转设置,避免容器拦截旋转请求:
extension UINavigationController { override open var supportedInterfaceOrientations: UIInterfaceOrientationMask { return topViewController?.supportedInterfaceOrientations ?? .portrait } override open var shouldAutorotate: Bool { return topViewController?.shouldAutorotate ?? false } } extension UITabBarController { override open var supportedInterfaceOrientations: UIInterfaceOrientationMask { return selectedViewController?.supportedInterfaceOrientations ?? .portrait } override open var shouldAutorotate: Bool { return selectedViewController?.shouldAutorotate ?? false } }
这样设置后,弹出模态页时设备可以自由旋转到允许的方向;模态页关闭后,发起的ViewController会立刻回到竖屏并保持锁定状态,不会跟着设备旋转。
内容的提问来源于stack exchange,提问作者Tometoyou




