Search code examples
iosswiftmpmediaquery

Get Album titles for indexed uitableview using MPMediaQuery in swift?


I'm finding the deeply nested structure of the MPMediaQuery difficult to navigate.

I'm trying to get the title(s) of albums for each Section to display in an indexed UITableView.

The basic query and code to get all albums:

let myQuery:MPMediaQuery = MPMediaQuery.albumsQuery()
myQuery.groupingType = MPMediaGrouping.Album
let allAlbums = myQuery.collections

// This prints the total number of albums (either way works)
// Or so I thought - but this does not give the album count per section
// I don't know what this is returning!
print("number albums \(myQuery.collections?.count)")
print("number albums \(allAlbums?.count)")

// this prints out the title of each album
for album in allAlbums!{
    print("---------------")
    print("albumTitle \(album.representativeItem?.albumTitle)")
    print("albumTitle \(album.representativeItem?.valueForProperty(MPMediaItemPropertyAlbumTitle))")
}

This handles the TableView Index stuff:

  // create index title
    func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
        let sectionIndexTitles = myQuery.itemSections!.map { $0.title }
        return sectionIndexTitles
    }

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

    // tableview
    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return (myQuery.itemSections![section].title)
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // print("number of sections \(myQuery.itemSections?.count)")
        return (myQuery.itemSections?.count)!
    }

I'm at a loss to determine how to print out the Album titles for each section (where a section is "A", "B", etc) like:

A
Abbey Road
Achtung Baby
All The Young Dudes
B
Baby The Stars Shine Bright
C
Cosmic Thing

etc.....


Solution

  • I'm going to answer my own question.
    I've posted similar questions here on SO and everyone replying said this couldn't be done and that additional Arrays were needed plus custom sort routines. That's simply not true.
    This code uses the return from an Album Query to:
    1) Build a TableView index
    2) Add Albums by Title (using Apple's sorting) to table Sections
    3) Start playing an album when selected

    Here's the Swift code to prove it:

    // 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()
        }
    

    Also, here's a few helpful notes:

    1) List all the Albums from the query:

    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 out part of the query to see how it's constructed:

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

    I hope this helps some of you - if so up vote!