排查Swift中AVAudioRecorder的NSOSStatusErrorDomain错误(Code=1718449215)
错误原因与解决方案
错误码1718449215对应kAudioSessionErr_CategoryNotPermitted,核心问题是音频会话配置时机不对+权限请求与初始化顺序颠倒,以下是具体修复步骤:
关键问题分析
- 初始化时先调用
setUpRecorder(),但此时权限可能还处于undetermined状态,recordPermission()直接返回false,导致初始化失败。 - 音频会话激活时未处理可能的冲突(比如其他应用占用音频),也未设置必要的category选项。
- 文件名后缀与编码格式不匹配:用
kAudioFormatMPEG4AAC编码应该对应.m4a后缀,而非.mp3。
修复步骤
- 调整权限请求与初始化顺序:先请求权限,在权限授予后再初始化录制器。
- 完善音频会话配置:设置category时添加必要选项,激活会话时处理可能的错误。
- 添加重新初始化逻辑:权限授予后重新调用
setUpRecorder()。 - 修正文件后缀:将
.mp3改为.m4a。
修改后的完整代码
class Recorder : NSObject, AVAudioRecorderDelegate { let recordingName: String var audioRecorder: AVAudioRecorder? var isRecording = false init(recordingName: String) { self.recordingName = recordingName super.init() requestRecordPermission() } func filePath() -> URL { // 修正后缀为m4a,匹配AAC编码 let fileName = self.recordingName + ".m4a" let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let documentsDirectory = paths[0] return documentsDirectory.appendingPathComponent(fileName) } func requestRecordPermission() { AVAudioApplication.requestRecordPermission { [weak self] permission in guard let self = self else { return } if permission { print("已获取录音权限") // 权限授予后才初始化录制器 self.audioRecorder = self.setUpRecorder() } else { print("应用无录音权限") } } } func recordPermission() -> Bool { let permissionStatus = AVAudioApplication.shared.recordPermission switch permissionStatus { case .granted: return true case .denied: return false case .undetermined: print("录音权限未确定") return false @unknown default: print("录音权限状态需更新") return false } } func setUpRecorder() -> AVAudioRecorder? { guard recordPermission() else { return nil } let session = AVAudioSession.sharedInstance() do { // 添加options,适配不同场景,比如允许蓝牙输入 try session.setCategory(.record, mode: .default, options: .allowBluetooth) // 激活会话时处理可能的冲突,比如其他应用占用音频 try session.setActive(true, options: .notifyOthersOnDeactivation) let settings = [ AVFormatIDKey: Int(kAudioFormatMPEG4AAC), AVSampleRateKey: 44100, AVNumberOfChannelsKey: 2, AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue ] let audioRecorder = try AVAudioRecorder(url: filePath(), settings: settings) audioRecorder.delegate = self audioRecorder.isMeteringEnabled = true audioRecorder.prepareToRecord() return audioRecorder } catch let error { print("录制器初始化失败: \(error.localizedDescription)") return nil } } func toggleRecording() { guard let recorder = self.audioRecorder else { print("录制器未初始化,请检查权限") return } if isRecording { recorder.stop() isRecording = false } else { // 开始录制前再次确认会话状态 let session = AVAudioSession.sharedInstance() do { try session.setActive(true) } catch { print("激活音频会话失败: \(error)") return } if recorder.record() { isRecording = true } else { print("开始录制失败") } } } // 实现代理方法,处理录制完成或错误 func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) { if flag { print("录制完成,文件路径: \(recorder.url)") } else { print("录制失败") } isRecording = false } func audioRecorderEncodeErrorDidOccur(_ recorder: AVAudioRecorder, error: Error?) { if let error = error { print("录制编码错误: \(error)") } } }
代码点评
- 权限处理优化:将权限请求放在初始化第一步,确保权限授予后才初始化录制器,避免因权限未确定导致的初始化失败。
- 音频会话健壮性提升:添加category选项和会话激活的错误处理,适配更多场景(如蓝牙麦克风),同时处理与其他音频应用的冲突。
- 格式一致性修正:文件名后缀与编码格式匹配,避免后续播放时的兼容性问题。
- 错误反馈增强:在
toggleRecording()中添加录制器未初始化的提示,以及开始录制前的会话状态检查,便于调试。 - 代理方法补充:实现
AVAudioRecorderDelegate的核心方法,能及时获取录制完成或错误的状态,方便业务逻辑处理。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

