如何在AVKit中选择新视频时关闭画中画(PiP)播放的视频?
解决AVKit画中画模式下切换视频无法关闭旧视频的问题
嘿,这个场景我太熟悉了!当视频进入画中画(PiP)模式后,AVPlayerViewController确实会失去对它的直接控制权,这时候调用dismiss肯定没用——因为PiP是系统层面在管理视频了。不过别担心,有个很直接的解决方案,核心就是用AVPictureInPictureController来管理PiP状态,而不是只依赖AVPlayerViewController。
关键思路
你需要全局持有两个对象:
- 当前正在播放的
AVPlayer实例 - 对应的
AVPictureInPictureController实例
这样当用户选择新视频时,你可以直接通过AVPictureInPictureController停止旧视频的PiP状态,再清理旧播放器,最后启动新视频。
修改后的代码实现
// 在你的ViewController类中添加全局变量 var currentPlayer: AVPlayer? var currentPiPController: AVPictureInPictureController? func play(FileName filename: String, FileType type: String) { // 先处理正在播放的旧视频(包括PiP状态) if let existingPlayer = currentPlayer, let pipController = currentPiPController { // 如果旧视频正处于PiP模式,直接停止 if pipController.isPictureInPictureActive { pipController.stopPictureInPicture() } // 暂停播放器并释放资源 existingPlayer.pause() currentPlayer = nil currentPiPController = nil } // 准备新视频的播放 guard let path = Bundle.main.path(forResource: filename, ofType: type) else { print("找不到指定视频文件") return } let url = URL(fileURLWithPath: path) let newPlayer = AVPlayer(url: url) currentPlayer = newPlayer let playerVC = AVPlayerViewController() playerVC.player = newPlayer // 初始化PiP控制器(先检查设备是否支持PiP) if AVPictureInPictureController.isPictureInPictureSupported() { currentPiPController = AVPictureInPictureController(playerLayer: playerVC.playerLayer!) } // 全屏呈现新视频并开始播放 present(playerVC, animated: true) { newPlayer.play() } }
为什么这样能解决问题?
AVPictureInPictureController是专门用来管理PiP状态的系统类,不管视频是不是处于AVPlayerViewController的控制下,它都能直接操作PiP的启停- 全局持有播放器和PiP控制器,确保你能准确找到并清理旧的播放实例,避免多个视频同时播放
额外注意事项
- 别忘了在
Info.plist中添加画中画权限描述:<key>NSPictureInPictureUsageDescription</key> <string>允许视频以画中画模式播放,方便您同时使用应用其他功能</string> - 如果用户的设备不支持PiP(比如部分旧机型),
isPictureInPictureSupported()会返回false,这时候直接暂停旧播放器就行,不会有问题
内容的提问来源于stack exchange,提问作者iOSProgrammingIsFun
相关产品推荐
相关产品推荐

