SwiftUI界面在AVSpeech结束时卡顿问题求助
问题解决:语音播放结束后界面卡顿+音频会话停用失败
问题根源
音频会话停用操作阻塞主线程,加上停用失败的状态异常,导致界面滚动卡顿。错误出现在speechSynthesizer(_:didFinish:)方法中,同步执行的停用操作占用了主线程资源,同时会话状态处理不当引发报错。
修复方案
1. 后台线程执行音频会话停用
把停用操作移到后台线程,避免阻塞UI刷新:
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) { DispatchQueue.global(qos: .background).async { do { try AVAudioSession.sharedInstance().setActive(false, options: .notifyOthersOnDeactivation) } catch { print("Failed to deactivate audio session: \(error.localizedDescription)") } } }
2. 优化音频会话激活逻辑
激活会话前先检查状态,避免重复激活;同时简化线程切换,语音合成无需强制回主线程:
func speak(say: String) { DispatchQueue.global(qos: .userInitiated).async { let audioSession = AVAudioSession.sharedInstance() do { if !audioSession.isActive { try audioSession.setCategory(.playback, options: [.duckOthers]) try audioSession.setActive(true) } let utterance = AVSpeechUtterance(string: say) utterance.voice = AVSpeechSynthesisVoice(language: "en-US") utterance.rate = 0.5 self.synthesizer.speak(utterance) } catch { print("Audio session error: \(error.localizedDescription)") } } }
3. 可选:添加停用容错处理
若停用失败,可延迟重试或忽略(部分场景下会话被占用时停用失败不影响功能):
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) { DispatchQueue.global(qos: .background).async { let audioSession = AVAudioSession.sharedInstance() guard audioSession.isActive else { return } do { try audioSession.setActive(false, options: .notifyOthersOnDeactivation) } catch { print("Failed to deactivate audio session: \(error.localizedDescription)") DispatchQueue.main.asyncAfter(deadline: .now() + 1) { try? audioSession.setActive(false) } } } }
关键说明
AVAudioSession.setActive()是同步操作,耗时调用会阻塞当前线程,必须放到后台执行。AVSpeechSynthesizer.speak()无需强制在主线程调用,后台线程执行完全正常。- 激活前检查
isActive状态,可避免重复激活导致的会话状态混乱。
内容的提问来源于stack exchange,提问作者jbrito
相关产品推荐
相关产品推荐

