iOS 16中JW Player视频横屏模式无法激活的技术求助
iOS 16 下 JW Player 横屏适配方案
问题分析
iOS 16 对屏幕旋转的控制逻辑做了调整,原有的supportedInterfaceOrientations重写和forceLandscapeOnFullScreen属性不再直接生效,核心原因是系统优先遵循 Scene 层级的旋转配置,且需要主动请求几何更新才能触发旋转状态变更。
解决方案
1. 调整全局旋转配置(替换 AppDelegate 中的旧代码)
若你的 App 使用 SceneDelegate(iOS 13+ 推荐),在SceneDelegate.swift中实现以下方法,替代原 AppDelegate 中的旋转控制逻辑:
func windowScene(_ windowScene: UIWindowScene, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { if UIDevice.current.userInterfaceIdiom == .phone { // 默认竖屏,后续由 ViewController 动态调整 return .portrait } return .all }
若仍使用无 Scene 的 AppDelegate,保留原方法即可,但需确保 ViewController 的旋转配置能覆盖全局设置。
2. 在播放器所在 ViewController 中添加动态旋转控制
在包含 JW Player 的 ViewController 中,添加以下属性和方法,根据播放器全屏状态动态调整旋转权限:
// 标记是否处于视频全屏状态 private var isVideoFullscreen = false { didSet { if #available(iOS 16.0, *) { // iOS 16+ 必须主动请求几何更新 view.window?.windowScene?.requestGeometryUpdate(.iOS(interfaceOrientations: isVideoFullscreen ? .all : .portrait)) } else { setNeedsUpdateOfSupportedInterfaceOrientations() } // 进入全屏时强制设备横屏(增强兼容性) if isVideoFullscreen { UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation") } } } // 重写旋转权限 override var supportedInterfaceOrientations: UIInterfaceOrientationMask { if UIDevice.current.userInterfaceIdiom == .phone { return isVideoFullscreen ? .all : .portrait } return .all } // iOS 16+ 额外处理旋转回调,实现竖屏时关闭播放器 @available(iOS 16.0, *) override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) if UIDevice.current.orientation.isPortrait && isVideoFullscreen { jwplyr?.fullscreen = false isVideoFullscreen = false } }
3. 监听 JW Player 的全屏状态变化
实现 JWPlayerDelegate 方法,同步更新isVideoFullscreen状态:
extension YourViewController: JWPlayerDelegate { func player(_ player: JWPlayerController, didChangeFullscreen isFullscreen: Bool) { isVideoFullscreen = isFullscreen // 进入全屏时强制锁定横屏逻辑 if isFullscreen && UIDevice.current.userInterfaceIdiom == .phone { player.forceLandscapeOnFullScreen = true // 手动触发旋转确保生效 UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation") } } }
4. 调整播放器初始化代码
保留原有初始化逻辑,确保播放器视图正确添加到层级中:
func playLocalVideo(withKey key: String) { let videoFile = key let baseUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let assetUrl = baseUrl.appendingPathComponent(videoFile) let item = JWPlaylistItem() item.file = assetUrl.absoluteString let config = JWConfig() config.playlist = [item] config.controls = true config.autostart = true jwplyr = JWPlayerController(config: config) jwplyr?.delegate = self jwplyr?.fullscreen = true if UIDevice.current.userInterfaceIdiom == .phone { jwplyr?.forceLandscapeOnFullScreen = true } // 将播放器视图添加到当前控制器层级 if let player = jwplyr { player.view.frame = view.bounds view.addSubview(player.view) addChild(player) player.didMove(toParent: self) } }
关键说明
- iOS 16 必须调用
requestGeometryUpdate通知系统旋转权限变更,仅setNeedsUpdateOfSupportedInterfaceOrientations不再生效。 - 同步监听 JW Player 的全屏状态是核心,确保旋转权限与播放器状态匹配。
- 手动触发设备旋转是为了兼容部分场景下系统不会自动响应旋转的问题。
内容的提问来源于stack exchange,提问作者cesarcarlos
相关产品推荐
相关产品推荐

