如何检测Apple Music歌曲或播放队列的播放结束状态
检测Apple Music播放结束(单首/队列)
当然可以实现!用MPMusicPlayerController.applicationQueuePlayer()的时候,我们可以通过监听系统通知来捕获播放结束的事件,不管是单首歌曲播放完毕还是整个队列完成都能处理。下面是具体的实现思路和代码示例:
一、先开启播放通知
首先必须调用beginGeneratingPlaybackNotifications(),否则播放器不会发送任何状态变化的通知,这是很容易忽略的关键步骤:
let player = MPMusicPlayerController.applicationQueuePlayer() player.beginGeneratingPlaybackNotifications()
二、检测单首歌曲播放结束
单首歌曲播放完通常会触发两种场景:要么播放器自动切换到下一首(触发MPMusicPlayerControllerNowPlayingItemDidChange通知),要么如果是队列最后一首,播放器会进入停止状态(触发MPMusicPlayerControllerPlaybackStateDidChange通知)。
你可以结合这两个通知来精准判断:
- 监听
MPMusicPlayerControllerNowPlayingItemDidChange:当当前播放项发生变化时,说明上一首已经播放完毕 - 监听
MPMusicPlayerControllerPlaybackStateDidChange:当播放状态变为.stopped且当前仍有未播放项时,也能判定当前歌曲播放结束
注册通知的代码示例:
// 监听当前播放项切换 NotificationCenter.default.addObserver(forName: .MPMusicPlayerControllerNowPlayingItemDidChange, object: player, queue: .main) { _ in // 这里执行单首歌曲播放结束后的操作 print("单首歌曲播放完毕,已切换到下一首") } // 监听播放状态变化 NotificationCenter.default.addObserver(forName: .MPMusicPlayerControllerPlaybackStateDidChange, object: player, queue: .main) { notification in guard let player = notification.object as? MPMusicPlayerController else { return } if player.playbackState == .stopped, player.nowPlayingItem != nil { print("当前歌曲播放完毕(非队列最后一首)") } }
三、检测整个播放队列完成
当整个队列播放完毕时,播放器的nowPlayingItem会变为nil,同时播放状态切换为.stopped。在MPMusicPlayerControllerPlaybackStateDidChange的回调里,判断这两个条件即可:
if player.playbackState == .stopped && player.nowPlayingItem == nil { // 执行队列全部完成后的指定操作 print("所有歌曲都播放完了!") }
额外注意事项
- 记得在不需要监听的时候调用
player.endGeneratingPlaybackNotifications(),并移除通知观察者,避免内存泄漏 - 所有UI相关操作要放在主线程执行,所以通知队列建议用
.main - 如果用户手动暂停/停止播放,也会触发
.stopped状态,你可能需要结合播放历史或队列长度来区分是自然结束还是手动操作
内容的提问来源于stack exchange,提问作者Richard Hughes
相关产品推荐
相关产品推荐

