iOS 16已废弃attemptRotationToDeviceOrientation函数的替代方案
iOS 16+ 主动切换屏幕朝向的合规替代方案
attemptRotationToDeviceOrientation 在iOS 16被标记废弃后,苹果官方提供了基于UIWindowScene的几何更新API作为正代替代,完全可以覆盖点击按钮主动切换指定ViewController朝向的需求,具体实现方式如下:
前置基础配置
所有朝向切换的前提是先在项目的Info.plist或者Target的Deployment Info中,勾选上你需要支持的所有屏幕朝向,否则代码触发不会生效。
在需要自定义朝向的ViewController中,先重写两个基础控制属性,建议用变量动态控制返回值:
// 动态控制当前页面支持的朝向 var forceOrientation: UIInterfaceOrientationMask = .portrait override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return forceOrientation } override var shouldAutorotate: Bool { return true }
如果项目用了UINavigationController、UITabBarController这类容器控制器,需要重写容器类的这两个属性,把配置透传给当前可见的顶层ViewController,否则单页面的配置会被容器覆盖。
分版本实现切换逻辑
iOS 16+ 新API实现
使用UIWindowScene的requestGeometryUpdate方法主动请求朝向更新,这是苹果官方指定的替代方案,无私有API,过审无风险。
按钮点击触发切换的核心代码如下:
@objc func onTapOrientationChangeButton() { // 先更新当前页面的朝向支持配置 if forceOrientation == .portrait { forceOrientation = .landscapeRight } else { forceOrientation = .portrait } if #available(iOS 16.0, *) { // 拿到当前页面绑定的windowScene,多Scene场景不要取错 guard let windowScene = view.window?.windowScene else { return } // 构造朝向偏好,必须和上面设置的forceOrientation保持一致 let geometryPref = UIWindowScene.GeometryPreferences.iOS(interfaceOrientations: forceOrientation) windowScene.requestGeometryUpdate(geometryPref) { error in // 切换失败回调,比如传入了项目没勾选的朝向就会触发 debugPrint("朝向切换失败: \(error.localizedDescription)") } // 通知系统刷新当前页面的朝向支持配置 setNeedsUpdateOfSupportedInterfaceOrientations() } else { // iOS 15及以下版本保留原有逻辑即可 UIDevice.current.setValue(forceOrientation.deviceOrientationValue, forKey: "orientation") UIViewController.attemptRotationToDeviceOrientation() } }
老版本兼容用的映射扩展可以直接用这段:
extension UIInterfaceOrientationMask { var deviceOrientationValue: Int { switch self { case .portrait: return UIDeviceOrientation.portrait.rawValue case .landscapeRight: return UIDeviceOrientation.landscapeRight.rawValue case .landscapeLeft: return UIDeviceOrientation.landscapeLeft.rawValue case .portraitUpsideDown: return UIDeviceOrientation.portraitUpsideDown.rawValue default: return UIDeviceOrientation.portrait.rawValue } } }
注意事项
requestGeometryUpdate传入的朝向参数,必须和当前ViewController返回的supportedInterfaceOrientations值一致,否则会切换失败- 不要在AppDelegate中全局写死朝向返回值,如果需要全局控制,在
application(_:supportedInterfaceOrientationsFor:)方法中返回当前顶层ViewController实际支持的朝向即可 - 多窗口(Scene)场景下,必须取当前操作页面所在的windowScene,不要随便取第一个windowScene,否则会出现切换错窗口的问题
内容的提问来源于stack exchange,提问作者chaselop
相关产品推荐
相关产品推荐

