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

iOS 16.7及以上版本endGeneratingDeviceOrientationNotifications失效咨询

问题分析与解决方案

这不是iOS的Bug,而是苹果在iOS 16及后续版本中调整了设备旋转通知与屏幕旋转控制的关联机制——原本通过endGeneratingDeviceOrientationNotifications停止生成设备方向通知来锁定屏幕旋转的方式,已经不再生效。

机制变化说明

在iOS 15及更早版本中,停止设备方向通知会同时阻止系统向视图控制器发送旋转相关回调(如viewWillTransitionToSize),从而实现屏幕旋转锁定。但iOS 16开始,系统拆分了设备方向通知和屏幕旋转逻辑:即使停止生成UIDeviceOrientationDidChangeNotification通知,系统仍会基于硬件检测到的设备方向变化,触发视图控制器的布局更新回调。

替代实现方案

要在iOS 16+中实现应用内的屏幕旋转锁定,建议通过动态控制视图控制器支持的界面方向来实现,具体步骤如下:

1. 基于视图控制器的方向控制

重写目标视图控制器(如MainViewController)的supportedInterfaceOrientations方法,根据应用内的旋转锁定开关状态,动态返回允许的界面方向:

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    // 假设self.rotationLockEnabled是你的应用内开关状态变量
    if (self.rotationLockEnabled) {
        // 获取当前界面方向,返回仅允许该方向的掩码
        UIInterfaceOrientation currentOrientation = [UIApplication sharedApplication].statusBarOrientation;
        switch (currentOrientation) {
            case UIInterfaceOrientationPortrait:
                return UIInterfaceOrientationMaskPortrait;
            case UIInterfaceOrientationLandscapeLeft:
                return UIInterfaceOrientationMaskLandscapeLeft;
            case UIInterfaceOrientationLandscapeRight:
                return UIInterfaceOrientationMaskLandscapeRight;
            case UIInterfaceOrientationPortraitUpsideDown:
                return UIInterfaceOrientationMaskPortraitUpsideDown;
            default:
                return UIInterfaceOrientationMaskPortrait;
        }
    } else {
        // 返回应用默认支持的方向(根据你的需求调整)
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
}

2. 容器控制器的适配

如果你的视图控制器嵌套在UINavigationController或UITabBarController中,需要自定义容器控制器并重写supportedInterfaceOrientations,确保将方向控制权限传递给顶层子控制器:

// 自定义导航控制器示例
@interface CustomNavigationController : UINavigationController
@end

@implementation CustomNavigationController
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return self.topViewController.supportedInterfaceOrientations;
}
@end

3. 强制更新方向(可选)

当用户切换旋转锁定开关时,可以触发系统重新计算界面方向,确保锁定立即生效:

// iOS 12及以下
[[UIApplication sharedApplication] setStatusBarOrientation:[UIApplication sharedApplication].statusBarOrientation animated:NO];

// iOS 13+ 使用窗口场景
if (@available(iOS 13.0, *)) {
    UIWindowScene *windowScene = [UIApplication sharedApplication].connectedScenes.firstObject;
    UIWindowSceneGeometryPreferencesIOS *preferences = [[UIWindowSceneGeometryPreferencesIOS alloc] init];
    preferences.interfaceOrientations = [self supportedInterfaceOrientations];
    [windowScene requestGeometryUpdateWithPreferences:preferences errorHandler:^(NSError * _Nonnull error) {
        NSLog(@"方向更新失败: %@", error);
    }];
}

补充说明

endGeneratingDeviceOrientationNotifications方法现在仅用于停止接收UIDeviceOrientationDidChangeNotification通知,不再影响屏幕旋转的控制逻辑。因此你需要移除之前重复调用该方法的逻辑,替换为上述基于界面方向支持的实现方式。

内容的提问来源于stack exchange,提问作者Chris Hughes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:43:19