You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS自定义视频播放器启动画中画(PiP)后立刻停止失效问题求助

问题根因定位

1. PiP启动阶段错误销毁播放器视图

你在playerViewControllerWillStartPictureInPicture(PiP将要启动的回调)中直接调用了playerViewController.dismiss,这个操作会将AVPlayerLayer从视图层级中移除,而PiP和系统Pegasus服务的连接依赖AVPlayerLayer的有效实例,启动流程未完成就移除layer会直接导致XPC连接失效,也就是你控制台输出的4099错误。

2. 未执行PiP恢复回调的completionHandler

pictureInPictureController(_:restoreUserInterfaceForPictureInPictureStopWithCompletionHandler:)方法要求必须调用传入的completionHandler闭包,告知系统恢复操作是否完成,你当前实现完全没有调用这个闭包,系统会判定PiP流程异常,主动终止PiP会话。

修复方案

步骤1:调整PiP启动后的dismiss时机

首先给CustomVideoPlayerViewController的AVPictureInPictureControllerDelegate扩展新增启动完成的回调,把dismiss逻辑移到这个回调里:

extension CustomVideoPlayerViewController: AVPictureInPictureControllerDelegate {
func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
    videoPlayerDelegate?.playerViewControllerWillStartPictureInPicture(self)
}
// 新增启动完成回调
func pictureInPictureControllerDidStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
    videoPlayerDelegate?.playerViewControllerDidStartPictureInPicture(self)
}

func pictureInPictureControllerWillStopPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
    videoPlayerDelegate?.playerViewControllerWillStopPictureInPicture(self)
}

func pictureInPictureController(_ pictureInPictureController: AVPictureInPictureController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
    videoPlayerDelegate?.playerViewController(self, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler: completionHandler)
}}

步骤2:修改CustomVideoPlayerDelegate的实现

首先把dismiss逻辑移到启动完成的回调里,然后在恢复方法里补全completionHandler的调用:

extension TabBarViewController: CustomVideoPlayerDelegate {

func playerViewController(_ playerViewController: UHVideoPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
    shouldReleaseVideoPlayer = false
    let currentviewController = navigationController?.visibleViewController
    var restoreSuccess = false
    if currentviewController != playerViewController, currentviewController != nil {
        if !(currentviewController?.isKind(of: CustomVideoPlayerViewController.self) ?? false) {
            currentviewController?.present(playerViewController, animated: false) {
                restoreSuccess = true
                // 界面恢复完成后调用completionHandler
                completionHandler(restoreSuccess)
            }
            return
        }
    }
    // 不需要跳转的情况也要调用completionHandler
    completionHandler(true)
}

func playerViewControllerWillStartPictureInPicture(_ playerViewController: UHVideoPlayerViewController) {
    // 移除这里的dismiss逻辑
}

// 新增启动完成的代理方法实现
func playerViewControllerDidStartPictureInPicture(_ playerViewController: UHVideoPlayerViewController) {
    playerViewController.dismiss(animated: true, completion: nil)
}

func playerViewControllerWillStopPictureInPicture(_ playerViewController: UHVideoPlayerViewController) {
    if shouldReleaseVideoPlayer {
        currentVideoPlayer = nil
    }
    shouldReleaseVideoPlayer = true
}}

步骤3:补充代理方法声明

在CustomVideoPlayerDelegate的协议定义里补充playerViewControllerDidStartPictureInPicture的方法声明即可。

内容的提问来源于stack exchange,提问作者SPS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 18:06:05