如何解决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。
另见
-
Apple Dev Forum 1 // 未解决
-
Apple Dev Forum 2 // 归因于测试版 iOS/Xcode
-
Stackoverflow 1 // 未解决
-
Stackoverflow 2 // 参考下一个链接
-
Apple Dev Forum 3 // Xcode 12b5 中修复的声明
[...还有更多...]
代码
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 举报,一经查实,本站将立刻删除。