首页 经验

词汇宝、词汇魔方、简易物理、新维日语 均已提供鸿蒙版本,点此下载


iOS 16 屏幕旋转新方法

时间: 2025-11-30 19:43:36

(部分内容来自网络,其真实性存疑,为了避免对您造成误导,请谨慎甄别。)

🍎 iOS 16 屏幕旋转新方法


在 iOS 16 中,Apple 引入了新的 API 来替代 attemptRotationToDeviceOrientation() 和直接设置 UIDevice.orientation 的方式。


核心新 API 是:

- setNeedsUpdateOfSupportedInterfaceOrientations():这是 UIViewController 的实例方法,用于通知系统该视图控制器支持的方向已改变,应触发方向更新。这通常与你视图控制器的 supportedInterfaceOrientations 属性重写配合使用。

- UIWindowScene.requestGeometryUpdate(_:):当你需要强制设备旋转到特定方向时,应使用此方法。它接受一个 UIWindowSceneGeometryPreferences 对象(具体来说,在 iOS 上通常是 UIWindowSceneGeometryPreferencesIOS)来指定期望的方向。


下面的表格对比了新旧 API 的使用场景和方法:


使用场景旧方法 (iOS 16 前)新方法 (iOS 16 及以上)
通知系统方向需更新UIViewController.attemptRotationToDeviceOrientation()yourViewController.setNeedsUpdateOfSupportedInterfaceOrientations()
强制设备旋转KVC设置 UIDevice.orientationUIWindowScene.requestGeometryUpdate(_:)


🛠️ 新API代码示例


这里是如何在你的扫雷游戏中应用新 API 的示例。


1. 在 AppDelegate 中设置全局方向控制


这个基础部分和之前类似,确保 AppDelegate 中存在 orientationLock 属性并在对应方法中返回它。


class AppDelegate: NSObject, UIApplicationDelegate {
    // 定义一个全局变量来控制方向锁
    static var orientationLock: UIInterfaceOrientationMask = .portrait {
        didSet {
            // 当方向锁改变时,通知所有视图控制器更新方向
            UIViewController.attemptRotationToDeviceOrientation()
        }
    }

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {         return AppDelegate.orientationLock     } }


2. 在特定视图控制器(如你的 MinesweeperView)中控制方向


在你的 MinesweeperView 对应的 UIViewController 中,重写方向相关属性,并在适当的时候(如视图出现/消失时)更新全局方向锁并调用新 API。


// 假设这是你的 MinesweeperView 所在的 ViewController
class GameViewController: UIViewController {
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        // 定义此控制器支持的方向
        return .all // 或者 [.portrait, .landscapeLeft, .landscapeRight]
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置内容视图,例如你的 SwiftUI MinesweeperView
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        // 进入游戏时,解锁方向或设置为所有方向
        AppDelegate.orientationLock = .all
        
        // 🆕 关键:通知系统需要更新支持的方向
        if #available(iOS 16.0, *) {
            self.setNeedsUpdateOfSupportedInterfaceOrientations()
        } else {
            // 对于 iOS 16 以下,仍使用旧方法(但你的项目目标可能已经不需要了)
            UIViewController.attemptRotationToDeviceOrientation()
        }
        
        // 🆕 可选:如果你希望一进入此页面就强制横屏,可以使用更强力的方法
        forceLandscapeIfNeeded()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        // 离开游戏时,恢复竖屏锁定
        AppDelegate.orientationLock = .portrait
        // 🆕 通知系统更新
        if #available(iOS 16.0, *) {
            self.setNeedsUpdateOfSupportedInterfaceOrientations()
        } else {
            UIViewController.attemptRotationToDeviceOrientation()
        }
    }
    
    // 🆕 强制横屏的方法(使用 iOS 16 新 API)
    private func forceLandscapeIfNeeded() {
        guard #available(iOS 16.0, *) else { return }
        
        // 获取当前的 window scene
        guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
        
        // 创建横屏偏好设置
        let geometryPreferences = UIWindowSceneGeometryPreferencesIOS(interfaceOrientations: .landscape)
        
        // 请求更新几何结构(即旋转屏幕)
        windowScene.requestGeometryUpdate(geometryPreferences) { error in
            print("强制横屏请求完成,错误: $String(describing: error))")
        }
    }
}


3. 在 SwiftUI 中集成


由于你的 MinesweeperView 是 SwiftUI 视图,你需要通过 UIViewControllerRepresentable 将其包装,或者在 SwiftUI 的生命周期事件中调用上述逻辑。一个更SwiftUI的方式是使用自定义修饰符或 onAppear 来触发方向变化。


// 在 MinesweeperView 的 body 中或 .onAppear 修饰符里
struct MinesweeperView: View {
    var body: some View {
        // ... 你的扫雷游戏UI
        .onAppear {
            // 通知需要更新方向
            if #available(iOS 16.0, *) {
                // 可能需要获取当前的 UIViewController
                // 一种常见做法是通过 Notification 或 Environment 将请求传递到 UIKit 层
                // 这里简单示意:假设你有一个方法来处理方向改变
                AppDelegate.orientationLock = .all
                // 调用一个全局函数来触发 setNeedsUpdate...
                triggerOrientationUpdate()
            }
        }
        .onDisappear {
            AppDelegate.orientationLock = .portrait
            triggerOrientationUpdate()
        }
    }
}

// 需要一个方法来找到当前最顶层的 ViewController 并调用 setNeedsUpdate... // 这部分代码通常放在你的 AppDelegate 或一个全局工具类中 func triggerOrientationUpdate() {     if #available(iOS 16.0, *) {         // 找到当前活跃的窗口场景和视图控制器         guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,               let rootVC = windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController else { return }                  // 递归找到当前呈现的视图控制器         func findTopViewController(from vc: UIViewController?) -> UIViewController? {             if let nav = vc as? UINavigationController {                 return findTopViewController(from: nav.visibleViewController)             } else if let tab = vc as? UITabBarController, let selected = tab.selectedViewController {                 return findTopViewController(from: selected)             } else if let presented = vc?.presentedViewController {                 return findTopViewController(from: presented)             }             return vc         }                  if let topVC = findTopViewController(from: rootVC) {             topVC.setNeedsUpdateOfSupportedInterfaceOrientations()         }     } else {         UIViewController.attemptRotationToDeviceOrientation()     } }


希望这些新的 API 和示例代码能帮你解决问题!如果还有不清楚的地方,请随时提问。


还有问题,向AI提问。


上一个 简易化学 - 综合性化学学习与实验辅助平台 文章列表 下一个 首先在 Info.plist 中锁定方向

(汉语/英语/日语/法语/德语)语音助手(识别/合成),智能翻译,高中物理动画,数据分析,数据可视化,电话: 18201798243(同v)

最新

工具

© 2019-至今 适观科技

沪ICP备17002269号