iOS16適配 屏幕旋轉(zhuǎn)橫屏

背景

iOS16之前轉(zhuǎn)屏方法setOrientation:, 16之后使用無效.
雖然Xcode14/iOS16提供了新的api但還是beta版, 不能直接打包上線, 所以要在舊版適配新版本.
怎么適配 嘗試了很多方法, 比如橫屏?xí)r直接present一個(gè)橫屏VC, 但耗時(shí)耗力, 怎么花最小代價(jià)適配iOS16, 看下面...

未升級Xcode14提前調(diào)試iOS16

下載iOS16系統(tǒng)支持包
放到這個(gè)件夾下, 重啟Xcode就可以了
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport

iOS16新增轉(zhuǎn)屏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 轉(zhuǎn)屏Error: %@",error);
    }];

但在升級xcode14之前不能直接調(diào)用到, 可以通過獲取方法IMP調(diào)用
所以可以先這么適配, 上代碼:

+ (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方法不調(diào)用
            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 轉(zhuǎn)屏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方法, 調(diào)轉(zhuǎn)屏方法后立即處理UI, 可能造成界面錯(cuò)亂.

歡迎大佬評論交流????

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容