从 MPMediaLibrary 获取大量歌曲到 UITableView

Posted

技术标签:

【中文标题】从 MPMediaLibrary 获取大量歌曲到 UITableView【英文标题】:Fetching large number of songs from MPMediaLibrary into a UITableView 【发布时间】:2018-03-05 19:39:37 【问题描述】:

我有一个表格视图,其中包含音乐库中所有歌曲的列表。 起初,我正在获取所有歌曲并将它们的信息保存到这样的数组中:

var songs = [Song]()
private func loadSongs()
    let itunesSongs = MPMediaQuery.songs().items
    if itunesSongs == nil 
        return;
    
    for song in itunesSongs!
        let artist = song.albumArtist
        let trackTitle = song.title
        let image = song.artwork?.image(at: CGSize(width: 90, height: 90))
        let url = song.assetURL?.absoluteString ?? ""
        let song1 = Song(title: trackTitle ?? "", artist: artist ?? "", image: image, url: url)
        songs.append(song1)
    


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cellIdentifier = "SongTableViewCell"
        guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? SongCell  else 
            fatalError("The dequeued cell is not an instance of SongCell.")
        
        let song = playerManager.songs[indexPath.row]
        cell.setAttributes(song: song)

        cell.preservesSuperviewLayoutMargins = false
        return cell
    

当我在拥有超过 10000 首歌曲的设备上进行测试时,启动应用程序大约需要 5-10 秒。所以我修改了填充表格视图的方式如下:

var itunesSongs: MPMediaQuery.songs().items
func getSong(index: Int) -> Song 
    if(index >= songs.count)
        let song = itunesSongs![index]
        let ans = Song(title: song.title ?? "", artist: song.albumArtist ?? "", image: song.artwork?.image(at: CGSize(width: 90, height: 90)), url: song.assetURL?.absoluteString ?? "")
        songs.append(ans)
    
    return songs[index]

所以我会在tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) 中使用getSong(),而不是使用songs 数组。

问题已解决,应用程序正常启动。但是,有时,我会在return songs[index] 行上得到Fatal error: Index out of range。 当我快速滚动并且每次都使用不同的索引时会发生这种情况。我尝试一次获取 100 首歌曲而不是 1 首歌曲,但这也没有解决问题。

我正在考虑使用后台线程来填充 songs 数组,但不确定这是否是正确的方法。

【问题讨论】:

你在 numberOfRows 中设置的计数是多少???? @Sh_Khan itunesSongs?.count 【参考方案1】:

问题是表格视图没有按顺序调用getSong()。例如,表格视图可以调用getSong(6),然后调用getSong(3)。我将函数更新为:

func getSong(index: Int) -> Song 
    while (index >= songs.count)
        let song = itunesSongs![songs.count]

        let ans = Song(title: song.title ?? "", artist: song.albumArtist ?? "", image: song.artwork?.image(at: CGSize(width: 90, height: 90)), url: song.assetURL?.absoluteString ?? "")
        songs.append(ans)
    
    return songs[index]

【讨论】:

【参考方案2】:

一种可能的解决方案

根本不要使用歌曲数组。也许将大量项目(10000)附加到歌曲数组中需要时间。而是

像这样获取viewdidLoad()中的歌曲

让 itunesSongs = MPMediaQuery.songs().items

在 cellforRowAt 中,从 itunesSongs(标题、艺术家等)获取歌曲数据填充您的单元格并返回。像这样的东西

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

    let cellIdentifier = "SongTableViewCell"
    guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? SongCell  else 
        fatalError("The dequeued cell is not an instance of SongCell.")
    
    let song = itunesSongs[indexPath.row]
    cell.setAttributes(song: song)

    cell.preservesSuperviewLayoutMargins = false
    return cell

【讨论】:

以上是关于从 MPMediaLibrary 获取大量歌曲到 UITableView的主要内容,如果未能解决你的问题,请参考以下文章

如何从列表视图中的项目单击中获取歌曲在android中

从音频文件中获取专辑封面、歌曲名称、专辑名称和艺术家姓名

从歌曲中获取当前音频频率 - Java(也许使用 FFT?)

如何解决 NSAppleMusicUsageDescription 错误

以编程方式访问 iCloud 音乐库下载和 iCloud 状态

从java项目的资源文件夹中获取所有文件名