You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不旋转前序UIViewController的情况下实现横竖屏展示与关闭

iOS竖屏应用横屏控制器返回后视图异常的解决办法

一、强制指定视图控制器永远竖屏

直接在需要保持竖屏的前序视图控制器里重写以下两个方法,让它完全不响应旋转事件:

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .portrait
}

override var shouldAutorotate: Bool {
    return false
}

如果你的项目是iOS13及以上的SceneDelegate架构,还要在SceneDelegate里做全局旋转适配,只允许横屏控制器触发旋转:

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    // 先拿到当前最上层的控制器
    guard let topVC = window?.rootViewController?.topMostViewController else {
        return .portrait
    }
    // 如果是横屏控制器,开放左右横屏权限;否则锁死竖屏
    if topVC is LandscapeViewController {
        return .landscapeLeft.union(.landscapeRight)
    }
    return .portrait
}

这里需要给UIViewController加个扩展,用来获取当前最上层的控制器:

extension UIViewController {
    var topMostViewController: UIViewController {
        if let presentedVC = presentedViewController {
            return presentedVC.topMostViewController
        }
        return self
    }
}

二、修复UITableView的布局异常

要是旋转后UITableView出现contentOffset乱跳、cell布局错位这类问题,试试这几招:

  • 在前序控制器的viewWillAppear里强制刷新布局:
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    tableView.reloadData()
    // 重置contentOffset到顶部,避免错位
    tableView.contentOffset = .zero
    // 强制更新约束
    tableView.setNeedsLayout()
    tableView.layoutIfNeeded()
}
  • 检查UITableView的约束,别用硬编码的宽度/高度,尽量用leading、trailing这类相对superview的约束。
  • 自定义cell的话,在layoutSubviews里重新调整子视图布局,确保旋转后能自动适配:
override func layoutSubviews() {
    super.layoutSubviews()
    contentView.subviews.forEach { $0.setNeedsLayout() }
}

三、更优雅的横屏展示方案

不想折腾多窗口的话,可以直接在竖屏窗口里用模态方式展示横屏控制器,靠视图变换模拟横屏效果,还支持左右旋转:

class LandscapeViewController: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 根据当前设备方向调整旋转角度
        let angle: CGFloat
        if UIDevice.current.orientation == .landscapeRight {
            angle = CGFloat(Double.pi/2)
        } else {
            angle = CGFloat(-Double.pi/2)
        }
        // 给视图加旋转变换
        view.transform = CGAffineTransform(rotationAngle: angle)
        view.bounds = UIScreen.main.bounds
        view.center = CGPoint(x: UIScreen.main.bounds.midX, y: UIScreen.main.bounds.midY)
    }

    // 允许左右横屏旋转
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .landscapeLeft.union(.landscapeRight)
    }

    override var shouldAutorotate: Bool {
        return true
    }
}

内容的提问来源于stack exchange,提问作者Utku Eray

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:05:03