美文网首页iOSiOS开发问题解决
iOS16适配 屏幕旋转横屏

iOS16适配 屏幕旋转横屏

作者: 贤宇 | 来源:发表于2022-07-28 13:25 被阅读0次
    背景

    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适配 屏幕旋转横屏

        本文链接:https://www.haomeiwen.com/subject/quxxwrtx.html