iOS16适配 屏幕旋转横屏

背景

iOS16之前转屏方法, 16之后无效, 导致界面错乱.
虽然Xcode14/iOS16提供了新的api但还是beta版, 不能直接打包上线, 所以要在旧版适配新版本.
怎么适配 尝试了很多方法, 比如横屏时直接present一个横屏VC, 但耗时耗力, 怎么花最小代价适配iOS16, 看下面...

未升级Xcode14提前调试iOS16

下载iOS16系统支持包
放到这个件夹下, 重启Xcode就可以了
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport

iOS16新增转屏api
    UINavigationController *nav = [TYToolsUtil topViewController].navigationController;
    [nav setNeedsUpdateOfSupportedInterfaceOrientations];
    
    NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
    UIWindowScene *ws = (UIWindowScene *)array.firstObject;
    UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] init];
    geometryPreferences.interfaceOrientations = UIInterfaceOrientationMaskLandscapeRight;
    [ws requestGeometryUpdateWithPreferences:geometryPreferences
        errorHandler:^(NSError * _Nonnull error) {
        NSLog(@"iOS 16 转屏Error: %@",error);
    }];

但在升级xcode14之前不能直接调用到, 可以通过获取方法IMP调用
所以可以先这么适配, 上代码:

+ (void)setDevOri:(UIDeviceOrientation)ori {

    @try {
        // ios16使用新的api
        if (@available(iOS 16.0, *)) {
            UIInterfaceOrientationMask oriMask = UIInterfaceOrientationMaskPortrait;
            if (ori == UIDeviceOrientationPortrait) {
                oriMask = UIInterfaceOrientationMaskPortrait;
            } else if (ori == UIDeviceOrientationLandscapeLeft) {
                oriMask = UIInterfaceOrientationMaskLandscapeRight;
            } else if (ori == UIDeviceOrientationLandscapeRight) {
                oriMask = UIInterfaceOrientationMaskLandscapeLeft;
            } else {
                return;
            }
            // 防止appDelegate supportedInterfaceOrientationsForWindow方法不调用
            UINavigationController *nav = [TYToolsUtil topViewController].navigationController;
            SEL selUpdateSupportedMethod = NSSelectorFromString(@"setNeedsUpdateOfSupportedInterfaceOrientations");
            if ([nav respondsToSelector:selUpdateSupportedMethod]) {
                (((void (*)(id, SEL))[nav methodForSelector:selUpdateSupportedMethod])(nav, selUpdateSupportedMethod));
            }
            
            NSArray *array = [[[UIApplication sharedApplication] connectedScenes] allObjects];
            UIWindowScene *ws = (UIWindowScene *)array.firstObject;
            Class GeometryPreferences = NSClassFromString(@"UIWindowSceneGeometryPreferencesIOS");
            id geometryPreferences = [[GeometryPreferences alloc] init];
            [geometryPreferences setValue:@(oriMask) forKey:@"interfaceOrientations"];
            SEL selGeometryUpdateMethod = NSSelectorFromString(@"requestGeometryUpdateWithPreferences:errorHandler:");
            void (^ErrorBlock)(NSError *error) = ^(NSError *error){
                  NSLog(@"iOS 16 转屏Error: %@",error);
            };
            if ([ws respondsToSelector:selGeometryUpdateMethod]) {
                (((void (*)(id, SEL,id,id))[ws methodForSelector:selGeometryUpdateMethod])(ws, selGeometryUpdateMethod,geometryPreferences,ErrorBlock));
            }

        } else {
            
            if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
                SEL selector = NSSelectorFromString(@"setOrientation:");

                if ([UIDevice currentDevice].orientation == ori) {
                    NSInvocation *invocationUnknow = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
                    [invocationUnknow setSelector:selector];
                    [invocationUnknow setTarget:[UIDevice currentDevice]];
                    UIDeviceOrientation unKnowVal = UIDeviceOrientationUnknown;
                    [invocationUnknow setArgument:&unKnowVal atIndex:2];
                    [invocationUnknow invoke];
                }
                
                NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
                [invocation setSelector:selector];
                [invocation setTarget:[UIDevice currentDevice]];
                UIDeviceOrientation val = ori;
                [invocation setArgument:&val atIndex:2];
                [invocation invoke];
            }
        }        

    } @catch (NSException *exception) {
        
    } @finally {
        
    }
}

欢迎大佬评论交流

你可能感兴趣的:(iOS16适配 屏幕旋转横屏)