【问题标题】:Dynamically switching device orientation with single ViewController使用单个 ViewController 动态切换设备方向
【发布时间】:2021-02-10 00:20:20
【问题描述】:

我目前正在开发一个应用程序,该应用程序具有一个 ViewController 和一个 WKWebView 对象,该对象充当 Web 应用程序的客户端。它使用 JavaScript 通信和注入来允许原生 Swift 中的对象与 WebView 交互。

我的目标

我有一个函数,urlDidChange(_ url: String),它会在 WKWebView 的原始 URL 值更改时触发。我正在尝试根据所述新url 的值动态设置方向限制,并在满足条件后强制旋转设备以适应这些限制。

我不确定这些额外信息是否重要,但我想我还是会包含它:UIViewController 也嵌入在 UINavigationController 中。原生 NavBar 确实帮助客户端感觉更像原生应用。我没有为它设置任何自定义类,只是使用let navBar = navigationController?.navigationBar

所需的示例用法

func urlDidChange(_ url: String) {
    if url.contains("/dashboard") {
        UIInterfaceOrientationMask = .portrait
    } else if url.contains("/builder") {
        UIInterfaceOrientationMask = [.portrait, .landscapeRight]
    } else {
        UIInterfaceOrientationMask = .all
    }
    // Set new orientation properties
    // Force device rotation based on newly set properties
    UIViewController.attemptRotationToDeviceOrientation()   
}

当前代码

这是我目前的设置。我尝试了以下方法,但没有成功:

enum Page {
    
    var orientation: UIInterfaceOrientationMask {
        switch self {
        case .login:        return getDeviceOrientation()
        case .dashboard:    return getDeviceOrientation()
        case .newProject:   return getDeviceOrientation()
        case .builder:      return getDeviceOrientation()
        case .other:        return getDeviceOrientation()
        }
    }
    
    func getDeviceOrientation() -> UIInterfaceOrientationMask {
        let phone = Device.isPhone()
        switch self {
        case .login:
            if phone { return .portrait }
            else { return .all }
        case .dashboard:
            if phone { return .portrait }
            else { return .all }
        case .newProject:
            if phone { return .portrait }
            else { return .all }
        case .builder:
            if phone { return [.portrait, .landscapeRight] }
            else { return .all }
        case .other:
            if phone { return .portrait }
            else { return .all }
        }
    }

视图控制器

最后,为了应用新的方向属性,我使用了这个:

func urlDidChange(_ url: String) {
    let page = Page.get(forURL: url)    // Returns Page case for current URL
    
    UIDevice.current.setValue(page.orientation.rawValue, forKey: "orientation")
    UIViewController.attemptRotationToDeviceOrientation() 
}

奖金问题

是否有更有效的方法使用枚举将设备属性与我的 Page 枚举组合(即 case .builderDevice.isPhoneDevice.isPad 时的不同返回值)?

正如您在上面的代码中看到的,我只是使用 if 语句来确定现在要提供哪个输出:

case .builder:
    if phone { return [.portrait, .landscapeRight] }
    else { return .all }

【问题讨论】:

    标签: ios swift uiviewcontroller uinavigationcontroller wkwebview


    【解决方案1】:

    如果您的 ViewController 在 UINavigationController 中,这可能就是原因。您可以尝试使用自定义 UINavigationController,从您的 ViewController 中检索方向吗?像这样的:

    struct OrientationConfig {
        let phone: UIInterfaceOrientationMask
        let pad: UIInterfaceOrientationMask
    
        static let defaultConfig = OrientationConfig(phone: .portrait, pad: .all)
    }
    
    enum Page {
        case login
        case dashboard
        case newProject
        case builder
        case other
    
        static let orientationConfigs: [Page:OrientationConfig] = [
            .login: OrientationConfig.defaultConfig,
            .dashboard: OrientationConfig.defaultConfig,
            .newProject: OrientationConfig.defaultConfig,
            .builder: OrientationConfig(phone: [.portrait, .landscapeRight],
                                        pad: .all),
            .other: OrientationConfig.defaultConfig
        ]
    }
    
    class MyViewController: UIViewController {
    
        var page: Page = .login
    
        override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            if let config = Page.orientationConfigs[page] {
                return Device.isPhone ? config.phone : config.pad
            }
            return super.supportedInterfaceOrientations
        }
    
    }
    
    class MyNavigationController: UINavigationController {
        override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            if let viewController = topViewController as? MyViewController {
                return viewController.supportedInterfaceOrientations
            }
            return super.supportedInterfaceOrientations
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多