我在 iOS 9/10 和 iOS 11 之间看到了不同的行为,当发生音频路由更改时(例如,您插入耳机)在 AVAudioPlayerNode 上安排未来的缓冲区。有没有人遇到过类似的事情,你是如何解决的?请注意,我大约两周前在 Apple 的 AVFoundation 支持论坛上报告了这个问题,但收到的回复完全为零。
显示此问题的代码如下所示 - 首先简要说明:该代码是一个简单的循环,它重复安排缓冲区在未来的某个时间播放。该过程通过调用“runSequence”方法开始,该方法安排音频缓冲区在未来某个时间播放,并将完成回调设置为嵌套方法“audioCompleteHandler”。完成回调再次调用“runSequence”方法,该方法调度另一个缓冲区并使进程永远运行。在这种情况下,除非完成处理程序正在执行,否则总是有一个缓冲区被调度。各个地方的“trace”方法是内部打印方法,仅在调试时进行打印,因此可以忽略。
在音频路由更改通知处理程序 (handleAudioRouteChange) 中,当新设备可用时(case .newDeviceAvailable),代码会重新启动引擎和播放器,重新激活音频会话并调用“runSequence”以将循环重新启动。
这一切在 iOS 9.3.5 (iPhone 5C) 和 iOS 10.3.3 (iPhone 6) 上运行良好,但在 iOS 11.1.1 (iPad Air) 上失败。失败的本质是 AVAudioPlayerNode 不播放音频而是立即调用完成处理程序。这会导致失控的情况。如果我再次删除启动循环的行(如代码所示),它在 iOS 11.1.1 上运行良好,但在 iOS 9.3.5 和 iOS 10.3.3 上失败。这个失败是不同的:音频刚刚停止,在调试器中,我可以看到循环没有循环。
所以,一个可能的解释是,在 iOS 9.x 和 iOS 10.x 下,当音频路由发生变化时,未来的预定缓冲区是未预定的,而在 iOS 11.x 下,未来预定的缓冲区不是未预定的。
这导致了两个问题: 1. 有没有人看到过与此类似的行为?解决方案是什么?2. 任何人都可以向我指出在音频路由更改(或音频中断)发生时描述引擎、播放器和会话的确切状态的文档吗?
private func runSequence() {
// For test ony
var timeBaseInfo = mach_timebase_info_data_t()
mach_timebase_info(&timeBaseInfo)
// End for test only
let …Run Code Online (Sandbox Code Playgroud)