ios - 使用单个 ViewController 动态切换设备方向

标签 ios swift uiviewcontroller uinavigationcontroller wkwebview

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

我的目标

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

我不确定这些额外的信息是否重要,但我认为无论如何我都会包含它:UIViewController 也嵌入在 UINavigationController 中。原生导航栏确实让客户端感觉更像是原生应用程序。我没有为其设置任何自定义类,只是使用 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 }
        }
    }

View Controller

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

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() 
}

奖励问题

是否有更有效的方法使用枚举将设备属性与我的页面枚举相结合(即 case .builder ,当 Device.isPhone 时具有不同的返回值或者当Device.isPad)时?

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

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

最佳答案

如果您的 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
    }
}

关于ios - 使用单个 ViewController 动态切换设备方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64559218/

相关文章:

swift - 没有实现 methodSignatureForSelector : Unrecognized selector (NSTimer)

ios - CocoaPods pod 安装。无法导入模块

ios - 为什么 iOS 在 didReceiveMemoryWarning 释放后不自动旋转从 Nib 加载的 View ?

javascript - 防止 :hover on touch in iOS

ios - 以编程方式在 Swift 中设置 tabBarItem 标题

iphone - 如何从 iOS 中的警报通知操作启动 View Controller ?

ios - UICollectionViewCell 没有选择项目不工作

objective-c - 使用 navigationController 的白屏

ios - 关闭一个 View Controller 并以相同的方法呈现一个新的 - swift

objective-c - 检查正在使用的应用程序版本