我目前正在开发一个应用程序,它有一个 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/