繁体   English   中英

Force View Controller Orientation 是否在 iOS 16 beta 中工作

[英]is Force View Controller Orientation working in iOS 16 beta

根据 iOS 和 iPadOS 16 Beta 3 发行说明:- 尝试通过setValue:forKey:UIDevice上设置方向不受支持且不再有效。 相反,他们说使用:preferredInterfaceOrientationForPresentation。

就我而言,通过使用preferredInterfaceOrientationForPresentationrequestGeometryUpdate强制视图控制器方向在 iOS 16 beta 中不起作用。

以前, UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")工作正常。

这个对我有用:

    import Foundation
    import UIKit

    extension UIViewController {
    
    func setDeviceOrientation(orientation: UIInterfaceOrientationMask) {
        if #available(iOS 16.0, *) {
            let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
            windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))
        } else {
            UIDevice.current.setValue(orientation.toUIInterfaceOrientation.rawValue, forKey: "orientation")
        }
    }
}

extension UIInterfaceOrientationMask {
    var toUIInterfaceOrientation: UIInterfaceOrientation {
        switch self {
        case .portrait:
            return UIInterfaceOrientation.portrait
        case .portraitUpsideDown:
            return UIInterfaceOrientation.portraitUpsideDown
        case .landscapeRight:
            return UIInterfaceOrientation.landscapeRight
        case .landscapeLeft:
            return UIInterfaceOrientation.landscapeLeft
        default:
            return UIInterfaceOrientation.unknown
        }
    }
}

如何使用它?

只需在您的 UIViewController 上调用它:

setDeviceOrientation(orientation: .landscapeRight)

编辑

更完整的解决方案:

import UIKit

final class DeviceOrientation {
    
    static let shared: DeviceOrientation = DeviceOrientation()
    
    // MARK: - Private methods
    
    private var windowScene: UIWindowScene? {
        return UIApplication.shared.connectedScenes.first as? UIWindowScene
    }
    
    // MARK: - Public methods
    
    func set(orientation: UIInterfaceOrientationMask) {
        if #available(iOS 16.0, *) {
            windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))
        } else {
            UIDevice.current.setValue(orientation.toUIInterfaceOrientation.rawValue, forKey: "orientation")
        }
    }
    
    var isLandscape: Bool {
        if #available(iOS 16.0, *) {
            return windowScene?.interfaceOrientation.isLandscape ?? false
        }
        return UIDevice.current.orientation.isLandscape
    }
    
    var isPortrait: Bool {
        if #available(iOS 16.0, *) {
            return windowScene?.interfaceOrientation.isPortrait ?? false
        }
        return UIDevice.current.orientation.isPortrait
    }
    
    var isFlat: Bool {
        if #available(iOS 16.0, *) {
            return false
        }
        return UIDevice.current.orientation.isFlat
    }
}

extension UIInterfaceOrientationMask {
    var toUIInterfaceOrientation: UIInterfaceOrientation {
        switch self {
        case .portrait:
            return UIInterfaceOrientation.portrait
        case .portraitUpsideDown:
            return UIInterfaceOrientation.portraitUpsideDown
        case .landscapeRight:
            return UIInterfaceOrientation.landscapeRight
        case .landscapeLeft:
            return UIInterfaceOrientation.landscapeLeft
        default:
            return UIInterfaceOrientation.unknown
        }
    }
}

如何使用它:

 DeviceOrientation.shared.set(orientation: .portrait)

我注意到我的问题似乎可以通过调用以下方法解决:

[UIViewController setNeedsUpdateOfSupportedInterface

你可以试一试。

setValue:forKey是旧NSObject ( NSKeyValueCoding ) 的方法。 UIDevice class 没有官方记录和支持。 使用它正在考虑使用私有 api。 苹果可以随时终止它。

我在下面的代码中遇到的问题是,我在关闭模态视图时尝试这样做,而它下面的视图更新得不够快。 如果我将 requestGeometryUpdate 放在一个单独的按钮上,那么当我关闭视图时它就会起作用。

if #available(iOS 16.0, *) {

    let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene

    windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait))

} 

Apple 发布了新的 API 替换为 setValue:forKey:"orientation"。 苹果更新

guard let windowScene = view.window?.windowScene else { return }
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .landscape)) { error in
// Handle denial of request.
}

但我对UIDevice.orientationDidChangeNotification有问题,它不工作

这个对我有用。

在 AppDelegate 中,

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

鉴于controller,

(UIApplication.shared.delegate as? AppDelegate)?.orientation = .landscapeRight
                    
let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: .landscapeRight))

UIApplication.navigationTopViewController()?.setNeedsUpdateOfSupportedInterfaceOrientations()

按照 Apple 的文档,您需要

使用指定的几何首选项对象请求更新窗口场景的几何图形。

https://developer.apple.com/documentation/uikit/uiwindowscene/3975944-requestgeometryupdate/

因此,使用示例中的代码,您可以使用requestGeometryUpdatesetNeedsUpdateOFSupportedInterface更改我们在视图中设置方向的方式

public extension UIViewController {

func deviceOrientation(orientation: UIInterfaceOrientationMask) {
    if #available(iOS 16.0, *) {
        guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
        else { return }
        windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: orientation))
        self.setNeedsUpdateOfSupportedInterfaceOrientations()
    }
  }
}

我尝试了以上所有解决方案,但它们似乎并非 100% 有效。 通过这篇文章https://developer.apple.com/forums/thread/707735我得到了提示。 让我们试试下面的代码。 它对我有用。

if #available(iOS 16.0, *) {
        DispatchQueue.main.async {
            UIViewController.attemptRotationToDeviceOrientation()
                
            let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
                windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: orientation)) { error in
                print(error)
                print(windowScene?.effectiveGeometry)
            }
               navigationController?.topViewController?.setNeedsUpdateOfSupportedInterfaceOrientations()
        }
   }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM