iOS 16 场景方向问题

15
每当我尝试在我的控制器上只允许纵向方向时,我总是收到这个错误: 错误域=UISceneErrorDomain 代码=101 "视图控制器不支持任何请求的方向。请求的方向:landscapeLeft;支持的方向:portrait" 用户信息={NSLocalizedDescription=视图控制器不支持任何请求的方向。请求的方向:landscapeLeft;支持的方向:portrait}
我调用了这个方法:
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 )
                }
            }
        }
    }

有人遇到过同样的问题吗?

也许这个与你相关? https://developer.apple.com/forums/thread/707735 - Usman Ismail
5个回答

2

J.Y.527提供了一个解决方案:https://dev59.com/llEG5IYBdhLWcg3wIUpb#73735976

这看起来像是一个变通方法,但在我的情况下它已经解决了问题。

诀窍是在需要旋转时更新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")
    }
  
}

1
嗨@Jeffrey,你能否提供一下如何在AppDelegate.m文件中定义方向函数的方法?我已经按照OrrHsiao所提到的方式定义了这个函数(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { return UIInterfaceOrientationMaskAll; },但是还是出现了“AppDelegate的值没有成员'orientation'”的错误。请给予我建议。 - Brad

1
您可以尝试像这样,这对我有效。
- (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];
    }
}

通过遍历windowScene.windows,这个方法对我很有效。谢谢。 - Ajeet Pratap Maurya

0

是的,我遇到了同样的问题,并按照以下方式解决了它。提供的错误清楚地表明我们正在尝试旋转设备,而我们在应用程序的某个地方限制其仅在一种模式下使用。在我的情况下,我在Appdelegate.swift中实现了以下方法:

var myOrientation: UIInterfaceOrientationMask = .portrait

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

因此,将其限制为仅使用纵向模式会导致应用程序在横向模式下无法旋转。

通过将方向更改为所有方向,使其正常工作。

var myOrientation: UIInterfaceOrientationMask = .portrait

0
这里有一个最好和简单的解决方案,适用于所有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)

在这里,我将我的屏幕方向锁定为全屏,并强制更改为竖屏。

祝你好运!


嘿,谢谢!在iOS 16.4上,这对我来说效果非常好。我看到一个警告,说UIViewController.attemptRotationToDeviceOrientation()在iOS 16+已被弃用,所以应该进入else的情况吗?我还没有测试的设置。明天试一下。 - RedRoosterMobile
@RedRoosterMobile 这在我的案例中有效。如果有任何问题,请告诉我。 - Amrit Tiwari
对我没有起作用 - undefined

-1

在Appdelegate中尝试一下

  • (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { return UIInterfaceOrientationMaskAll; }

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community
@OrrHsiao 我也遇到了同样的问题,我在AppDelegate.m中包含了你提到的UIInterOrientationMask函数,并在一个.swift文件中按照Jeffrey提供的实现方式将其包含在一个单独的函数中,但是我得到了编译器错误“类型'AppDelegate'没有成员'orientation'”。我来自RN背景,对obj-c和swift都很陌生。请问能否给我一些建议,因为我急需解决这个问题。 - Brad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接