swiftui - iOS 在 iOS 13 中播放音频引发 C++ 异常,冻结应用
问题描述
TL;博士:
下面的代码(它的所有十行,除了调试)
- 在 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 开发论坛 1 // 未解决
- Apple Dev Forum 2 // 归因于 beta 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...
我认为第一行是无害的,并且与模拟器的声音驱动程序有关。 是否还有其他人在 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 秒的延迟。
解决方案
推荐阅读
- javascript - 如何在没有任何性能问题的情况下渲染 Timer
- laravel - Laravel 测试迁移污染断言
- excel - 如何通过 Excel Power Query 访问 Clockify API
- c# - C# - 在内存中生成数据库备份脚本
- python - Python 通用数据引擎
- java - 如何在java中进行相互SSL身份验证
- ios - 如何在 Swift 中实现填空
- c# - 如何使用 C# 和 SQL Server 编写代码以从多个表中获取数据
- mongodb - 在 WSO2 EI 中使用 MongoDB
- google-cloud-iot - 为 Google IOT 运行源运行网关时出错