如何使用Swift将部分歌曲列表添加到UITableView?

时间:2016-03-05 20:37:42

标签: ios swift

我试图创建一个简单的音乐播放器,将UITableView分割成字母部分(如 Apple音乐播放器)列出设备上的所有歌曲。< / p>

有两个方面我无法弄清楚:

  1. 获取每个部分的歌曲数量,以便我可以创建 我的表中每个部分的行数正确
  2. 访问每个部分中的项目以填充部分单元格
  3. 我的代码已经很长了所以我会在这里提供相关信息:

    我得到这样的歌曲列表:

    let songsQry:MPMediaQuery = MPMediaQuery.songsQuery()
    

    这是我不确定的地方:

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        //How can I get the number of songs per Section to return??
        // this does not work:
        return songsQry.itemSections![0].count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
    
    //How do I get the song for the Section and Row??
        cell.textLabel?.text =  ????
        return cell
    }
    

2 个答案:

答案 0 :(得分:3)

我要回答我自己的问题 我在这里发布了类似的问题,所有人都回答说无法完成,需要额外的数组加上自定义排序例程。这根本不是真的。

但请注意,在我的示例代码中,我展示了如何为相册查询获得相同类型的结果。 Artist查询的代码几乎完全相同。

此代码使用从相册查询返回到:
1)构建TableView索引
2)按标题添加专辑(使用Apple的排序)到表格部分
3)选择时开始播放专辑

这是证明它的Swift代码:

// Set up a basic Albums query
let qryAlbums = MPMediaQuery.albumsQuery()
qryAlbums.groupingType = MPMediaGrouping.Album

// This chunk handles the TableView Index
    //create index title
    func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
        let sectionIndexTitles = qryAlbums.itemSections!.map { $0.title }
        return sectionIndexTitles
    }

    func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
        return index
    }

// This chunk sets up the table Sections and Headers
    //tableview
    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return (qryAlbums.itemSections![section].title)
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return (qryAlbums.itemSections?.count)!
    }

// Get the number of rows per Section - YES SECTIONS EXIST WITHIN QUERIES
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {        
        return qryAlbums.collectionSections![section].range.length
    }

// Set the cell in the table
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")

    // i'm only posting the pertinent Album code here.
    // you'll need to set the cell details yourself.

        let currLoc = qryAlbums.collectionSections![indexPath.section].range.location
        let rowItem = qryAlbums.collections![indexPath.row + currLoc]
        //Main text is Album name
        cell.textLabel!.text = rowItem.items[0].albumTitle
        // Detail text is Album artist
        cell.detailTextLabel!.text = rowItem.items[0].albumArtist!
        // Or number of songs from the current album if you prefer
        //cell.detailTextLabel!.text = String(rowItem.items.count) + " songs"

        // Add the album artwork
        var artWork = rowItem.representativeItem?.artwork        
        let tableImageSize = CGSize(width: 10, height: 10) //doesn't matter - gets resized below
        let cellImg: UIImageView = UIImageView(frame: CGRectMake(0, 5, myRowHeight-10, myRowHeight-10))
        cellImg.image = artWork?.imageWithSize(tableImageSize)
        cell.addSubview(cellImg)

        return cell
    }

// When a user selects a table row, start playing the album
// This assumes the myMP has been properly declared as a MediaPlayer
// elsewhere in code !!!

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let currLoc = qryAlbums.collectionSections![indexPath.section].range.location
        myMP.setQueueWithItemCollection(qryAlbums.collections![indexPath.row + currLoc])
        myMP.play()
    }

另外,这里有一些有用的注释:

1)列出查询中的所有相册:

for album in allCollections!{
    print("---------------")
    print("albumTitle \(album.items[0].albumTitle)")
    print("albumTitle \(album.representativeItem?.albumTitle)")
    print("albumTitle \(album.representativeItem?.valueForProperty(MPMediaItemPropertyAlbumTitle))")
} // each print statement is another way to get the title

2)打印出部分查询以查看其构造方式:

print("xxxx \(qryAlbums.collectionSections)")

我希望这对你们中的一些人有所帮助 - 如果是这样的话就投票了!

答案 1 :(得分:1)

这个想法很简单:

  

您需要创建一个包含对象的已排序数组 GroupedSongs   类型[String: [MPMediaItem]]字符和   数组包含与该字符对应的歌曲。该   [MPMediaItem]数组必须从title属性中排序。

设置表视图数据源

  1. 对于每个键,我们需要一个现在是主数组的部分
  2. 对于每个项目,我们需要一个数字歌曲,所以这将是数字 我们的tableView
  3. 的行数

    实施

    代码有评论,所以不再说话了:D

    var items: [[String: [MPMediaItem]]] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    
        items = loadSongsDividedByTitle()
    }
    
    // MARK: - Delegation
    
    // MARK: Table view datasource
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let object: [String: [MPMediaItem]] = items[section]
        let key = Array(object.keys)[0] // We always have one object there
        let songs: [MPMediaItem] = object[key]!
    
        return songs.count
    }
    
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return items.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
    
        // Load song from the array
        let object: [String: [MPMediaItem]] = items[indexPath.section]
        let key = Array(object.keys)[0] // We always have one object there
        let songs: [MPMediaItem] = object[key]!
        let song = songs[indexPath.row]
    
        // Bind title of the song to the cell text label
        cell.textLabel?.text = song.title
    
        return cell
    }
    
    // MARK: - Helpers
    
    func loadSongsDividedByTitle() -> [[String: [MPMediaItem]]] {
        guard var songs = MPMediaQuery.songsQuery().items else { return [] }
    
        // Sort songs
        songs = songs.sort({$0.title < $1.title})
    
        // Create a new dictionary to hold array of words for each letter
        var object: [String: [MPMediaItem]] = [:]
    
        // Songs holding a dictionary with music
        var groupedSongs : [[String: [MPMediaItem]]] = []
    
        // Enumerate in words
        for mediaItem in songs {
            guard let title: String = mediaItem.title! else { continue } // If we don't have the title skip the song
    
            // Use the first character as a key for each array
            let key = String(title.characters.first!)
    
            if var songGroup = object[key] {
                // If we have an array, then append the new word there
                songGroup.append(mediaItem)
                object[key] = songGroup
            } else {
                // Create an array for that key
                object[key] = [mediaItem]
            }
        }
    
        // Add every object into one big array
        for (key, value) in object {
            let sortedSongs = value.sort({$0.title < $1.title})
            groupedSongs.append([key: sortedSongs])
        }
    
        // Sort it alphabetically from a-z
        groupedSongs = groupedSongs.sort({Array($0.keys)[0] < Array($1.keys)[0]})
    
        return groupedSongs
    }
    

    带字符串的游乐场输出

    enter image description here