0

I want to fill a tableView with the last heard songs. With .nowPlayingItem I can get the very last song, but how can I get the songs heard before?

I think this question already has an answer at Retrieve list of songs ordered by last play time in iOS, but it is in Objective-C and I´m not able to translate it. Or is there an even better way to do it in Swift instead?

Community
  • 1
  • 1
J.Vongehr
  • 323
  • 1
  • 4
  • 18

2 Answers2

3

This is how you can do it in Swift,

let start = NSDate().timeIntervalSince1970

let songsQuery = MPMediaQuery.songsQuery()
if let songsArray = songsQuery.items {
    let sortedArray = songsArray.sort { item1, item2 in
        if let lastPlayedDateForItem1 = item1.lastPlayedDate, 
           let lastPlayedDateForItem2 = item2.lastPlayedDate {
            return lastPlayedDateForItem1.compare(lastPlayedDateForItem2) == .OrderedDescending
        }
        return false
    }
}
Sandeep
  • 20,908
  • 7
  • 66
  • 106
  • Thank you! How can i fill my tableView cells with it? Because `sortedArray` has no member like .title or .artist – J.Vongehr Mar 28 '16 at 18:31
  • For a large mdeia library, I would think that the `NSSortDescriptor` would be faster. I can't confirm because I only have two songs on my device. For a small library such as mine, it appears yours is faster. – wottle Mar 28 '16 at 18:37
3

You could do something like this:

    let startTime: NSTimeInterval = NSDate().timeIntervalSince1970
    let songsQuery: MPMediaQuery = MPMediaQuery.songsQuery()
    let songsArray: [MPMediaItem] = songsQuery.items!
    let songsNSArray : NSArray = NSArray(array: songsArray)

    let descriptor: NSSortDescriptor = NSSortDescriptor(key: MPMediaItemPropertyLastPlayedDate, ascending: false)
    let sortedResults: NSArray = songsNSArray.sortedArrayUsingDescriptors([descriptor])


    let finishTime: NSTimeInterval = NSDate().timeIntervalSince1970
    NSLog("Execution took %f seconds to return %i results.", finishTime - startTime, sortedResults.count)

The results would be stored in the sortedResults array

wottle
  • 13,095
  • 4
  • 27
  • 68
  • To get something like title, you could simply use a loop to get `sortedResults[i].title` – wottle Mar 28 '16 at 18:33
  • great, which kind of loop? – J.Vongehr Mar 28 '16 at 18:36
  • Well, because you are doing this in a tableview, you should get the list of songs when the view loads (or somewhere outside of the cellForRowAtIndexPath). Then, in `cellForRowAtIndexPath`, you would simply set the cell label to `sortedResults[indexPath.row].title` If you need help implementing a `UITableView`, I would recommend moving that to a new question, as it is too broad to add here. – wottle Mar 28 '16 at 18:40
  • Do you know why it crashes when i try `sortedResults[indexPath.row].imageWithSize(imageSize)`? @wottle – J.Vongehr Mar 28 '16 at 19:27
  • You'd have to put a breakpoint and see the reason. Are you sure all the songs have images. I don't think you can get the image straight from the `MPMediaItem` object. I think you need to get the `MPMediaItemArtwork` property on the item. – wottle Mar 28 '16 at 19:33
  • No, not all songs have images. The log i get is `unrecognized selector sent to instance`. What do you suggest? – J.Vongehr Mar 28 '16 at 19:38
  • Do a google search on `MPMediaItemArtwork` and you will find out how to get it from the MPMediaItem object. I think that is your problem. – wottle Mar 29 '16 at 19:08