Проблема с ориентацией сцены iOS 16

Я всегда получал эту ошибку, когда пытался разрешить только портретную ориентацию на своем контроллере:Error Domain=UISceneErrorDomain Code=101 «Ни одна из запрошенных ориентаций не поддерживается контроллером представления. Запрошено: landscapeLeft; Поддерживается: портрет» UserInfo={NSLocalizedDescription= Ни одна из запрошенных ориентаций не поддерживается контроллером представления. Запрошено: пейзажноелевое; Поддерживается: портрет}

      I called this method:
func updateOrientation(orientation: UIInterfaceOrientationMask) {
        if #available(iOS 16, *) {
            DispatchQueue.main.async {
                let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
                self.setNeedsUpdateOfSupportedInterfaceOrientations()
                self.navigationController?.setNeedsUpdateOfSupportedInterfaceOrientations()
                windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation)) { error in
                    print(error)
                    print(windowScene?.effectiveGeometry )
                }
            }
        }
    }

Did someone face the same issue ?

5 ответов

JY527 нашел решение:https://stackoverflow.com/a/73735976/2858994

Это похоже на обходной путь, но в моем случае он устранил проблему.

хитрость заключается в том, чтобы обновить поддерживаемую AppDelegate ориентацию, когда вам нужно повернуть.

В вашем AppDelegate:

          var orientation: UIInterfaceOrientationMask = .all
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
         return orientation
    }

Затем в вашем контроллере:

       static func SwitchOrientation(orientation : UIInterfaceOrientationMask, viewController : UIViewController){
 
    
    
    if #available(iOS 16.0, *) {
        (UIApplication.shared.delegate as? AppDelegate)?.orientation = orientation
                            
        let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
        windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))

        UIApplication.navigationTopViewController()?.setNeedsUpdateOfSupportedInterfaceOrientations()
        
        DispatchQueue.main.async {
                    let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
                    viewController.setNeedsUpdateOfSupportedInterfaceOrientations()
                    viewController.navigationController?.setNeedsUpdateOfSupportedInterfaceOrientations()
                    windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation)) { error in
                        print(error)
                        print(windowScene?.effectiveGeometry ?? "")
                    }
                }
    

    } else{
        UIDevice.current.setValue(orientation, forKey: "orientation")
    }
  
}

Можешь попробовать вот так, у меня это работает

      - (void)forceOrientation:(UIDeviceOrientation)orientation {
    if (@available(iOS 16.0, *)) {
        UIInterfaceOrientationMask orientationMask = (1 << orientation);
        [self setNeedsUpdateOfSupportedInterfaceOrientations];
        UIWindowScene *windowScene = (UIWindowScene *) 
        [UIApplication sharedApplication].connectedScenes.allObjects.firstObject;
        for (UIWindow *windows in windowScene.windows) {
            [windows.rootViewController setNeedsUpdateOfSupportedInterfaceOrientations];
        }
        UIWindowSceneGeometryPreferencesIOS *geometryPreferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:orientationMask];
        [windowScene requestGeometryUpdateWithPreferences:geometryPreferences errorHandler:nil];
    } else {
       [[UIDevice currentDevice] setValue:@(orientation) forKey:@"orientation"];
       [UIViewController attemptRotationToDeviceOrientation];
    }
}

Вот лучшее и простое решение, которое работает во всех версиях iOS, включая iOS 16+.

Первоначально установите значение ориентации в AppDelegate , поскольку здесь я заставляю приложение использовать только одну ориентацию.

      var orientationLock = UIInterfaceOrientationMask.portrait

и функционировать как

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

то вы можете создать класс расширения UIViewController как

       extension UIViewController {

    /// Lock your orientation
    func lockOrientation(_ orientation: UIInterfaceOrientationMask) {

        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationLock = orientation
        }

        if #available(iOS 16.0, *) {
            self.setNeedsUpdateOfSupportedInterfaceOrientations()
        }
    }

    /// OPTIONAL Added method to adjust lock and rotate to the desired orientation
    func lockOrientation(
        _ allowOrientation: UIInterfaceOrientationMask,
        andRotateTo rotateOrientation: UIInterfaceOrientationMask) {
            
        self.lockOrientation(allowOrientation)

        if #available(iOS 16.0, *) {
            UIViewController.attemptRotationToDeviceOrientation()
            let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
            windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: rotateOrientation))

            self.setNeedsUpdateOfSupportedInterfaceOrientations()

        } else {

            UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
            UINavigationController.attemptRotationToDeviceOrientation()
        }
    }
}

вы можете вызвать метод из своего контроллера, чтобы включить нужную вам ориентацию. Здесь я помещаю всю ориентацию.

              self.lockOrientation(.all)

И если вы хотите принудительно изменить ориентацию контроллера представления, которая блокирует ориентацию, позвоните как из вашего ViewController

          self.lockOrientation(.all, andRotateTo: .portrait)

Здесь я блокирую свою ориентацию для всех и заставляю ее переключаться на портретную.

Удачи!!!

Да, я столкнулся с той же проблемой и решил ее, как показано ниже. Предоставленная ошибка ясно говорит о том, что мы пытаемся повернуть устройство, где мы ограничиваем его использование только в одном режиме ранее где-то в приложении. В моем случае я был реализован ниже в Appdelegate.swift.

var myOrientation: UIInterfaceOrientationMask = .portrait

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

поэтому ограничение использования только портретного режима привело к сбою поворота приложения в ландшафтном режиме.

Меняя ориентацию на все, заставляет это работать.

      var myOrientation: UIInterfaceOrientationMask = .portrait

попробуй в Appdelegate

  • (UIInterfaceOrientationMask) приложение:(UIApplication *) приложение, поддерживаемое интерфейсом OrientationsForWindow:(UIWindow *) окно {return UIInterfaceOrientationMaskAll;}
Другие вопросы по тегам