iOS画中画restoreUserInterface方法观看YouTube后未调用问题求助
restoreUserInterfaceForPictureInPictureStopWithCompletionHandler未调用的问题 我之前也碰到过一模一样的情况!当其他视频类App抢占了系统的PiP会话后,自己App的恢复回调没触发,确实挺头疼的。
问题原因分析
这种情况通常是因为系统的PiP会话被其他App接管后,你的App的PiP状态被系统强制终止,但没有走常规的用户主动触发恢复的流程,导致restoreUserInterfaceForPictureInPictureStopWithCompletionHandler方法无法正常唤起。毕竟当另一个App启动PiP时,iOS会自动结束当前活跃的PiP会话,这时候你的App可能处于后台甚至挂起状态,系统不会主动触发恢复界面的回调。
可行的解决方案
下面几个方法可以帮你覆盖这种场景:
监听PiP停止通知,做兜底处理
除了依赖代理回调,一定要注册AVPictureInPictureControllerDidStopPictureInPictureNotification通知,这个通知会在PiP会话无论以何种方式结束时都触发,包括被其他App抢占的情况。示例代码如下:// 在初始化AVPictureInPictureController的地方注册通知 NotificationCenter.default.addObserver( self, selector: #selector(handlePiPStopped(_:)), name: .AVPictureInPictureControllerDidStopPictureInPicture, object: yourPiPController ) // 处理通知的回调方法 @objc private func handlePiPStopped(_ notification: Notification) { // 在这里执行界面恢复逻辑,比如回到播放页面 guard let window = UIApplication.shared.windows.first else { return } if let playbackVC = window.rootViewController?.presentedViewController as? PlaybackViewController { playbackVC.restorePlaybackInterface() // 如果有需要,手动处理completionHandler的完成逻辑 } }检查后台权限配置
确保你的App在Info.plist中配置了后台音频播放权限:添加UIBackgroundModes数组,包含audio项。没有这个权限的话,App进入后台后系统会限制其接收回调和通知的能力,很可能导致恢复逻辑失效。确认PiP代理的有效性
检查AVPictureInPictureController的delegate是否正确设置,并且代理对象没有被提前释放。比如如果用视图控制器作为代理,要保证它的生命周期和PiP控制器一致,避免因为代理被释放而导致回调无法触发。监听App激活事件,补充恢复逻辑
在SceneDelegate(或AppDelegate)中监听sceneDidBecomeActive(_:)方法,当App从后台回到前台时,主动检查是否需要恢复播放界面:func sceneDidBecomeActive(_ scene: UIScene) { // 检查当前是否有需要恢复的播放界面 guard let window = scene as? UIWindowScene else { return } if let playbackVC = window.windows.first?.rootViewController?.presentedViewController as? PlaybackViewController { if playbackVC.isPiPSessionStoppedNeedRestore { playbackVC.restorePlaybackInterface() } } }这一步可以作为最后兜底,确保无论什么场景下App激活时都能回到正确的播放界面。
另外,也可以在pictureInPictureControllerDidStopPictureInPicture(_:)代理方法中同步处理恢复逻辑,这个方法同样会在PiP会话结束时被调用,和通知形成双重保障。
内容的提问来源于stack exchange,提问作者harry

