【问题标题】:Shuffle NSMutableArray with 'Shuffle Albums' for up next queue (MediaPlayer)?使用“随机播放专辑”将 NSMutableArray 随机播放以用于下一个队列(MediaPlayer)?
【发布时间】:2015-05-08 21:45:02
【问题描述】:

我已经设法创建了一个(几乎)完美运行的下一个排队系统。我可以毫无问题地移动、删除和添加歌曲到列表中。我遇到的唯一问题是,当用户决定使用随机播放模式(例如MPMusicShuffleMode.Songs)时,下一个视图仍显示旧顺序(假设随机播放模式设置为关闭)。应用程序 Ecoute 具有类似的排队系统,但在洗牌时也可以使用。

我发现 Ecoute 不使用 MPMusicShuffleMode,如果你在 Ecoute 中按随机播放后进入股票音乐播放器,它保持不变。我想出了一种方法来显示洗牌歌曲的正确顺序(只需洗牌 NSMutableArray 并将其设置为新队列)。真正的问题是当用户想要“随机播放专辑”时我将如何随机播放这个数组?如果有帮助,NSMutableArray 包含 MPMediaItem

非常感谢。

编辑:

这种尝试有效,但歌曲数量的时间呈指数增长。 2000首歌曲大约需要25-35秒,非常慢。

else if(self.shuffleMode == "Songs"){
        self.shuffleMode = "Albums"
        self.shuffle.setTitle("Shuffle Albums", forState: UIControlState.Normal)
        var queueCopy = NSMutableArray(array: self.queue.items)
        var newQueue = NSMutableArray(array: [])

        var albums = MPMediaQuery.albumsQuery().collections as [MPMediaItemCollection]
        var albumsCopy = NSMutableArray(array: albums)
        shuffleArray(albumsCopy)

        for album in albumsCopy{
            for item in queueCopy{
                if (album.representativeItem!.valueForProperty(MPMediaItemPropertyAlbumTitle) as NSString == item.valueForProperty(MPMediaItemPropertyAlbumTitle) as NSString){
                    for(var i = 0; i < album.items!.count; i++){
                        if(album.items![i].valueForProperty(MPMediaItemPropertyTitle) as NSString == item.valueForProperty(MPMediaItemPropertyTitle) as NSString){
                            newQueue.addObject(item as MPMediaItem)
                        }
                    }
                }
            }
        }

        let newQueueToSet = MPMediaItemCollection(items: newQueue)
        let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        appDelegate.currentQueue = newQueueToSet
        self.queue = newQueueToSet

        self.player.setQueueWithItemCollection(newQueueToSet)

}

编辑 2:

设法将其缩短到 8 秒,但与 Ecoute 的 1 到 2 秒相差甚远。
8 秒版本:

        var albumNames = [String]()
        for item in queueCopy{
            albumNames.append(item.valueForProperty(MPMediaItemPropertyAlbumTitle) as NSString)
        }

        let unique = NSSet(array: albumNames).allObjects as [MPMediaItem]
        var uniqueAlbumNames = NSMutableArray(array: unique)
        shuffleArray(uniqueAlbumNames)

        for name in uniqueAlbumNames{
            for item in queueCopy{
                if item.valueForProperty(MPMediaItemPropertyAlbumTitle) as NSString == name as NSString{
                    newQueue.addObject(item as MPMediaItem)
            }
        }
}

最终编辑:

我坚持的最后一段代码。近 3000 首歌曲大约需要 7-8 秒。

    @IBAction func shufflePressed(sender: AnyObject) {

    if self.shuffleMode == "Off"{
        self.shuffleMode = "Songs"
        self.shuffle.setTitle("Shuffle All", forState: UIControlState.Normal)
        self.shuffle.setTitle("Shuffling", forState: UIControlState.Highlighted)


        var queueCopy = NSMutableArray(array: self.queue.items)
        self.unshuffledQueueCopy = self.queue

        shuffleArray(queueCopy)
        let newQueue = MPMediaItemCollection(items: queueCopy)
        let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        appDelegate.currentQueue = newQueue
        self.queue = newQueue

        self.player.setQueueWithItemCollection(newQueue)

    }
    else if(self.shuffleMode == "Songs"){
        self.shuffleMode = "Albums"
        self.shuffle.setTitle("Shuffle Albums", forState: UIControlState.Normal)

        var queueCopy = NSMutableArray(array: self.queue.items)
        var newQueue = NSMutableArray(array: [])

        var albums = MPMediaQuery.albumsQuery().collections as [MPMediaItemCollection]
        var albumsCopy = NSMutableArray(array: albums)
        shuffleArray(albumsCopy)


        // Takes 8 seconds for 3000 songs

        var albumNames = [String]()

        for item in queueCopy{
            albumNames.append(item.valueForProperty(MPMediaItemPropertyAlbumTitle) as NSString)
        }

        let unique = NSSet(array: albumNames).allObjects as [MPMediaItem]
        var uniqueAlbumNames = NSMutableArray(array: unique)
        shuffleArray(uniqueAlbumNames)


        for name in uniqueAlbumNames{
            for item in queueCopy{
                if item.valueForProperty(MPMediaItemPropertyAlbumTitle) as NSString == name as NSString{
                    newQueue.addObject(item as MPMediaItem)
                }
            }
        }

        let newQueueToSet = MPMediaItemCollection(items: newQueue)
        let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        appDelegate.currentQueue = newQueueToSet
        self.queue = newQueueToSet

        self.player.setQueueWithItemCollection(newQueueToSet)

    }
    else if(self.shuffleMode == "Albums"){
        self.shuffleMode = "Off"
        self.shuffle.setTitle("Shuffle", forState: UIControlState.Normal)
        var queueCopy = NSMutableArray(array: self.unshuffledQueueCopy.items)
        var nowPlayingItem = self.player.nowPlayingItem
        for(var i = 0; i < queueCopy.count; i++){
            if(queueCopy[i] as MPMediaItem == nowPlayingItem){
                self.fromIndex = i
            }
        }
        let newQueue = MPMediaItemCollection(items: queueCopy)
        let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        appDelegate.currentQueue = newQueue
        self.queue = newQueue

        self.player.setQueueWithItemCollection(newQueue)
        self.fromItem = newQueue.items[fromIndex + 1] as MPMediaItem

    }

【问题讨论】:

  • 你的问题是关于如何洗牌 NSMutableArray 中的一些项目?
  • @Avt 是的,但按专辑而不是歌曲

标签: ios algorithm swift nsmutablearray mpmediaitem


【解决方案1】:

所以在伪代码中它看起来像下面这样。

  1. 循环数组只制作一个新的专辑数组
  2. 随机播放新专辑数组
  3. 循环新专辑数组,在原始数组中查找该专辑中的项目。
  4. 在比赛中,将这些歌曲写入第三个数组,该数组将成为您的新播放列表。

谢谢

【讨论】:

  • 谢谢,我相信这行得通。对于我的第一步,我从相册查询创建了一个新数组,然后按照其余部分进行操作。
  • 不幸的是它不是最有效的。在 iPhone 6 上随机播放 2000 首歌曲需要很长时间。我添加了上面的代码,看看你是否能找到更快的方法。谢谢
  • 看看你上面的代码,我会在提取专辑时进行第二阶段,一个字典。包含专辑->曲目。然后在重新填充时,它将添加整个项目数组。那可能会更快。但实际上你必须对代码进行分析,看看什么是慢的。你知道哪些宠物用的时间最多吗?
  • 可能是访问这些 MPMediaItem 上的元信息是缓慢的部分,所以如果您将数据分组而不需要继续查看音乐项目,您会看到速度提高。
  • 我确信 Ecoute 使用了未记录的 API。否则不可能达到这样的速度。我现在所拥有的就可以了,使用播放列表时速度非常快,所以没关系。我已将您的答案标记为答案,因为它有很大帮助。谢谢
猜你喜欢
  • 2023-01-23
  • 1970-01-01
  • 2014-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
相关资源
最近更新 更多