我正在尝试制作音乐播放器,目前我只能过滤专辑并将其放在播放列表的前面。

我想做的是随机播放音乐,然后当用户点击按钮继续播放仅来自当前正在播放的专辑中的歌曲时,完成后我想知道它的完成,因此可以更改UI元素,然后继续播放库中的所有音乐。

但是,发生的是它将耗尽专辑中的所有歌曲,然后播放该专辑中的所有歌曲,然后播放一首随机歌曲,然后在该首歌曲随机返回该专辑的整个过程。然后播放随机歌曲。专辑制作完成后,一旦它变成了蓝月亮,它就会随机播放歌曲。

单身我有

func getAllSongs(completion: @escaping (_ songs: [MPMediaItem]?) -> Void) {
MPMediaLibrary.requestAuthorization { (status) in
  if status == .authorized {
  let query = MPMediaQuery()
  let mediaTypeMusic = MPMediaType.music
  let audioFilter = MPMediaPropertyPredicate(value: mediaTypeMusic.rawValue, forProperty: MPMediaItemPropertyMediaType, comparisonType: MPMediaPredicateComparison.equalTo)
query.addFilterPredicate(audioFilter)
  let songs = query.items

completion(songs)
} else {
completion(nil)
  }
 }
}


func getSongsWithCurrentAlbumFor(item: MPMediaItem) -> MPMediaQuery {
  let albumFilter = MPMediaPropertyPredicate(value: item.albumTitle, forProperty: MPMediaItemPropertyAlbumTitle, comparisonType: MPMediaPredicateComparison.equalTo)
  let predicates: Set<MPMediaPropertyPredicate> = [albumFilter]
  let query = MPMediaQuery(filterPredicates: predicates)
query.addFilterPredicate(albumFilter)
return query
 }

在我的VC中设置我使用的音频
let mediaPlayer = MPMusicPlayerApplicationController.applicationMusicPlayer


func setUpAudioPlayerAndGetSongsShuffled() {
  try?     AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategorySoloAmbient)
  try? AVAudioSession.sharedInstance().setActive(true)
  MBProgressHUD.showAdded(to: view, animated: true)
  MediaManager.shared.getAllSongs { (songs) in
  guard let theSongs = songs else {
  return
 }

self.newSongs = theSongs.filter({ (item) -> Bool in
return !self.playedSongs.contains(item)
 })

self.mediaPlayer.setQueue(with: MPMediaItemCollection(items: self.newSongs))

  self.mediaPlayer.shuffleMode = .songs
 self.mediaPlayer.repeatMode = .none
 self.mediaPlayer.prepareToPlay(completionHandler: { (error) in
DispatchQueue.main.async {
  MBProgressHUD.hide(for: self.view, animated: true)
}
  })
  }
  }

当用户点击按钮继续播放仅来自该专辑的歌曲时,我使用
if let nowPlaying = mediaPlayer.nowPlayingItem {
let albumQuery = MediaManager.shared.getSongsWithCurrentAlbumFor(item: nowPlaying)
 print("\(albumQuery)")
 let descriptor = MPMusicPlayerMediaItemQueueDescriptor(query: albumQuery)
 mediaPlayer.prepend(descriptor)
  }

重新阅读文档后,我注意到它说我应该更改为
let mediaPlayer = MPMusicPlayerApplicationController. applicationQueuePlayer

我无法弄清楚如何知道专辑何时耗尽,然后继续播放音乐库的其余部分。

非常高兴知道专辑中是否没有其他项目,以便用户无法按按钮来播放专辑中的更多内容

最佳答案

我发现了我的错误。我把逻辑放在错误的地方

在我的单身人士中,我添加了

func hasPlayedAllSongsFromAlbumFor(song: MPMediaItem) -> Bool {
if let allSongsInAlbum = getSongsWithCurrentAlbumFor(item: song).items {
  return lockedSongsContains(songs: allSongsInAlbum)
}
return true
}


func lockedSongsContains(songs: [MPMediaItem]) -> Bool {
for aSong in songs {
  if !lockedSongs.contains(aSong) {
    return false
  }
}
return true
}

我需要使用通知

我创建了一个函数,该函数在ViewDidLoad中有一个名为songChanged的通知

在songChanged函数中,我有
  if albumIsLocked && MediaManager.shared.hasPlayedAllSongsFromAlbumFor(song: nowPlaying) {
    albumLockButtonTapped(albumLockIconButton)
    MediaManager.shared.lockedSongs.removeAll()
  }

现在使用相册锁定按钮
if let nowPlaying = mediaPlayer.nowPlayingItem {
  if sender.isSelected {
    sender.isSelected = false
    albumIsLocked = false
    let lockRemovedQuery = MediaManager.shared.removeAlbumLockFor(item: nowPlaying)
    let lockRemovedDescriptor = MPMusicPlayerMediaItemQueueDescriptor(query: lockRemovedQuery)
    mediaPlayer.prepend(lockRemovedDescriptor)
    mediaPlayer.prepareToPlay()
  } else {
    sender.isSelected = true
    albumIsLocked = true
    let albumQuery = MediaManager.shared.getSongsWithCurrentAlbumFor(item: nowPlaying)
    let albumDescriptor = MPMusicPlayerMediaItemQueueDescriptor(query: albumQuery)
    mediaPlayer.prepend(albumDescriptor)
    mediaPlayer.prepareToPlay()
  }
}

关于ios - Media Player过滤并在专辑前面添加播放专辑,随机歌曲和专辑的功能,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48432855/

10-12 07:05