TestFlight中AVFAudio崩溃求助:Swift录音App真机正常TestFlight崩溃
iOS录音App TestFlight分发后崩溃问题排查
我用Swift开发了一款带录音和播放功能的App,在自己的真机上运行完全正常,但通过TestFlight分发到其他测试设备时出现崩溃。相关Swift 5.5代码如下:
func startRecording() { if recognitionTask != nil { recognitionTask?.cancel() recognitionTask = nil } let audioSession = AVAudioSession.sharedInstance() do { try audioSession.setCategory(AVAudioSession.Category.playAndRecord, mode: .spokenAudio, options: AVAudioSession.CategoryOptions.defaultToSpeaker) try audioSession.setActive(true, options: .notifyOthersOnDeactivation) } catch { print("audioSession properties weren't set because of an error.") } let bus = 0 let inputNode = audioEngine.inputNode let inputFormat = inputNode.outputFormat(forBus: bus) let outputFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: true)! let converter = AVAudioConverter(from: inputFormat, to: outputFormat)! inputNode.removeTap(onBus: 0) inputNode.installTap(onBus: bus, bufferSize: 1024, format: inputFormat) { (buffer: AVAudioPCMBuffer, when: AVAudioTime) in var newBufferAvailable = true let inputCallback: AVAudioConverterInputBlock = { inNumPackets, outStatus in if newBufferAvailable { outStatus.pointee = .haveData newBufferAvailable = false return buffer } else { outStatus.pointee = .noDataNow return nil } } let convertedBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(outputFormat.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate))! var error: NSError? let _ = converter.convert(to: convertedBuffer, error: &error, withInputFrom: inputCallback) self.recognitionRequest?.append(convertedBuffer) } audioEngine.prepare() try audioEngine.start() DispatchQueue.main.async { self.speechRecognize() } }
崩溃时捕获到的日志信息:
AVFAudio: AVAE_RaiseException(NSString*, ...) + 52
崩溃原因分析及修复方案
1. 隐私权限配置缺失
TestFlight分发的App会严格校验系统隐私权限,你的代码未处理麦克风权限请求,且Info.plist中大概率缺少NSMicrophoneUsageDescription键,这会直接导致App在调用录音功能时崩溃。
- 修复步骤:
- 在
Info.plist中添加NSMicrophoneUsageDescription键,值填写麦克风使用说明(如"需要访问麦克风进行录音操作")。 - 在启动录音前主动请求权限:
import AVFoundation func requestMicrophonePermission() { AVAudioSession.sharedInstance().requestRecordPermission { granted in DispatchQueue.main.async { if granted { self.startRecording() } else { // 提示用户前往设置开启麦克风权限 } } } }
startRecording()前先执行requestMicrophonePermission()。 - 在
2. 强制解包触发崩溃
代码中多处使用!强制解包(如音频格式、转换器、转换后的buffer),若设备不支持指定的音频参数,这些操作会直接触发崩溃。
- 修复:用可选绑定替代强制解包,处理创建失败的情况:
// 替换原输出格式创建代码 guard let outputFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: true) else { print("无法创建目标音频格式") return } guard let converter = AVAudioConverter(from: inputFormat, to: outputFormat) else { print("无法创建音频格式转换器") return } // 替换转换buffer创建代码 guard let convertedBuffer = AVAudioPCMBuffer(pcmFormat: outputFormat, frameCapacity: AVAudioFrameCount(outputFormat.sampleRate) * buffer.frameLength / AVAudioFrameCount(buffer.format.sampleRate)) else { print("无法创建转换后的音频缓存") return }
3. 音频会话错误未拦截
当前代码仅打印音频会话配置错误,未终止后续流程,若会话激活失败,继续执行audioEngine相关操作会引发崩溃。
- 修复:在catch块中终止流程并提示:
do { try audioSession.setCategory(.playAndRecord, mode: .spokenAudio, options: .defaultToSpeaker) try audioSession.setActive(true, options: .notifyOthersOnDeactivation) } catch { print("音频会话配置失败: \(error.localizedDescription)") // 可添加UI提示用户,直接返回不继续执行 return }
4. AudioEngine启动错误未处理
代码中try audioEngine.start()未用do-catch包裹,启动失败会直接崩溃。
- 修复:添加错误处理并清理资源:
do { try audioEngine.start() DispatchQueue.main.async { self.speechRecognize() } } catch { print("音频引擎启动失败: \(error.localizedDescription)") inputNode.removeTap(onBus: bus) // 清理已安装的tap }
内容的提问来源于stack exchange,提问作者Rafiul Hasan
相关产品推荐
相关产品推荐

