Проблема с ориентацией сцены 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;}