Swift中为两个AVAudioPlayer设置不同AVAudioSession类别问题
问题
我在Swift中创建了两个AVAudioPlayer实例,分别用于播放通知音效和音乐:
var soundPlayer: AVAudioPlayer? var musicPlayer: AVAudioPlayer?
播放通知音效时,需要设置AVAudioSession类别为.playback并启用.mixWithOthers选项,避免打断其他应用的音视频播放:
try AVAudioSession.sharedInstance().setCategory(.playback, options: [.mixWithOthers]) try AVAudioSession.sharedInstance().setActive(true)
而播放应用内音乐时,不能启用.mixWithOthers选项:
try AVAudioSession.sharedInstance().setCategory(.playback) try AVAudioSession.sharedInstance().setActive(true)
但AVAudioSession.sharedInstance()是单例,全局仅能设置一种配置,修改后会同时影响两个播放器。请问是否可以为每个AVAudioPlayer单独设置不同的setCategory类别?
回答
不能为单个AVAudioPlayer实例单独设置AVAudioSession类别——AVAudioSession是全局单例,它的配置会作用于整个应用的所有音频播放行为,所有音频播放器都会遵循当前会话的设置。
要满足你的需求,只能通过动态切换会话配置来适配不同的播放场景:
1. 播放通知音效的处理逻辑
播放音效前先保存当前会话的原有配置,避免覆盖正在播放的音乐设置,切换到混音模式完成播放后再恢复原有配置:
// 用于临时存储原有会话配置 private var originalSessionCategory: AVAudioSession.Category? private var originalSessionOptions: AVAudioSession.CategoryOptions? func playNotificationSound() { let session = AVAudioSession.sharedInstance() do { // 保存当前会话配置 originalSessionCategory = session.category originalSessionOptions = session.categoryOptions // 切换到混音模式 try session.setCategory(.playback, options: [.mixWithOthers]) try session.setActive(true) // 初始化并播放音效 guard let soundURL = Bundle.main.url(forResource: "notification", withExtension: "mp3") else { return } soundPlayer = try AVAudioPlayer(contentsOf: soundURL) soundPlayer?.delegate = self soundPlayer?.play() } catch { print("音效播放配置错误:\(error)") } } // 通过代理监听音效播放完成,恢复会话配置 extension YourViewController: AVAudioPlayerDelegate { func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) { guard let category = originalSessionCategory, let options = originalSessionOptions else { return } do { try AVAudioSession.sharedInstance().setCategory(category, options: options) try AVAudioSession.sharedInstance().setActive(true) } catch { print("恢复会话配置错误:\(error)") } } }
2. 播放应用内音乐的处理逻辑
直接设置会话为独占播放模式,激活后开始播放:
func playAppMusic() { do { try AVAudioSession.sharedInstance().setCategory(.playback) try AVAudioSession.sharedInstance().setActive(true) guard let musicURL = Bundle.main.url(forResource: "background", withExtension: "mp3") else { return } musicPlayer = try AVAudioPlayer(contentsOf: musicURL) musicPlayer?.numberOfLoops = -1 // 设置循环播放 musicPlayer?.play() } catch { print("音乐播放配置错误:\(error)") } }
注意事项
- 切换会话配置时必须捕获错误,避免因系统权限或音频状态冲突导致播放失败
- 如果需要在后台播放音频,需在Info.plist中添加
UIBackgroundModes并勾选audio权限
内容的提问来源于stack exchange,提问作者Rob
相关产品推荐
相关产品推荐

