iOS 在 iOS 13 中播放音频抛出 C++ 异常,冻结应用

问题描述

TL;DR:

下面的代码(全部十行,除调试外)

  • 在 iOS 13.x(模拟器)上失败(UI 冻结)
  • 在 14.x(模拟器和设备)上成功(音频播放)

我没有任何装有 iOS 13.x 的设备。但是...来自实时应用程序的分析表明它在 iOS 13 和 14 设备上都失败了。误报? (请参阅用 $$$ 注释的代码行。)

重现步骤

创建一个可以在 iOS 13 中运行的新 SwiftUI 项目。将 ContentView.swift 中的文本替换为以下代码添加名为 clip.mp3 的音频资源。构建并运行。

我使用的是 Xcode 12.4、macOS 11.1、Swift 5。

另见

代码

import SwiftUI
import AVKit

struct ContentView: View {
    var body: some View {
        Text("Boo!").onAppear { playClip() }
    }
}

var clipDelegate: AudioTimerDelegate!   // Hold onto it to forestall GC.
var player      : AVAudioPlayer!        // Ditto.

func playClip() {
    let u = Bundle.main.url(forResource: "clip",withExtension: "mp3")!
    player = try! AVAudioPlayer(contentsOf: u)
    clipDelegate = AudioTimerDelegate()  // Wait till Now to instantiate,for correct timing.
    player.delegate = clipDelegate
    player.preparetoPlay()
    NSLog("*** Starting clip play")    // NSLog so we get timestamp.
    player.play()

    // Wait 5 seconds and see if audioPlayerDidFinishPlaying.
    dispatchQueue.main.asyncAfter(deadline: .Now() + 5) {
        if let d = clipDelegate.clipDuration {
            NSLog("*** Caller   clip duration = \(d)")
        } else {
            NSLog("!!! Caller found nil clip duration")
            // $$$ In live app,post audio-freeze event to analytics.
        }
    }
}

class AudioTimerDelegate: NSObject,AVAudioPlayerDelegate {
    private var startTime : Double
    var clipDuration: Double?
    override init() {
        self.startTime = CFAbsoluteTimeGetCurrent()
        super.init()
    }
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer,successfully flag: Bool) {
        clipDuration = CFAbsoluteTimeGetCurrent() - startTime
        NSLog("*** Delegate clip duration = \(clipDuration!)")
    }
}

控制台输出

模拟器 iOS 14.4

音频播放并且控制台(为简洁起见进行了编辑)显示

14:33:17  [plugin] AddInstanceForFactory: No factory registered for ... F8BB1C28-...
14:33:17  *** Starting clip play
14:33:19  *** Delegate clip duration = 1.692...
14:33:22  *** Caller   clip duration = 1.692...

我认为第一行是无害的并且与模拟器的声音驱动程序有关。 Is anyone else getting this console message with AVAudioPlayer in Xcode 11 (and 11.1)?

设备 14.4

结果是一样的,没有AddInstanceForFactory抱怨。

模拟器 13.6

音频从不响起,委托回调从不运行,在控制台中我得到:

14:30:10  [plugin] AddInstanceForFactory: No factory registered for ... F8BB1C28-...
14:30:11  HALB_IOBufferManager_Client::GetIOBuffer: the stream index is out of range
14:30:11  HALB_IOBufferManager_Client::GetIOBuffer: the stream index is out of range
14:30:11  [aqme] AQME.h:254:IOProcFailure: AQDefaultDevice (1): output stream 0: null buffer
14:30:11  [aqme] AQMEIO_HAL.cpp:1774:IOProc: EXCEPTION thrown (-50): error != 0

14:30:26  [aqme] AQMEIO.cpp:179:AwaitIOCycle: timed out after 15.000s (0 1); suspension count=0 (IOSuspensions: )
14:30:26  CA_UISoundClient.cpp:241:StartPlaying_block_invoke: CA_UISoundClientBase::StartPlaying: AddRunningClient Failed (status = -66681).
14:30:26  *** Starting clip play
14:30:26  HALB_IOBufferManager_Client::GetIOBuffer: the stream index is out of range
14:30:26  HALB_IOBufferManager_Client::GetIOBuffer: the stream index is out of range
14:30:26  [aqme] AQME.h:254:IOProcFailure: AQDefaultDevice (1): output stream 0: null buffer
14:30:26  [aqme] AQMEIO_HAL.cpp:1774:IOProc: EXCEPTION thrown (-50): error != 0

14:30:41  [aqme] AQMEIO.cpp:179:AwaitIOCycle: timed out after 15.000s (1 2); suspension count=0 (IOSuspensions: )
14:30:46  !!! Caller found nil clip duration

备注

在失败案例中似乎有两个十五秒的延迟。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)