首页 > 解决方案 > iOS 在 iOS 13 中播放音频引发 C++ 异常,冻结应用

问题描述

TL;博士:

下面的代码(它的所有十行,除了调试)

我没有任何装有 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...

我认为第一行是无害的,并且与模拟器的声音驱动程序有关。 是否还有其他人在 Xcode 11(和 11.1)中使用 AVAudioPlayer 收到此控制台消息?

设备 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

评论

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

标签: swiftuifreezeavaudioplayer

解决方案


推荐阅读