Number of Albums By Artists

2.4k views Asked by At

That's my Question =)

MPMediaQuery *artistQuery = [MPMediaQuery artistsQuery];
NSArray *songsByArtist = [artistQuery collections];

How can I get the number of albums of each artists of the MPMediaItemCollections in songsByArtist ?

Exemple :

The Beatles 3 Albums

AC/DC 6 Albums

Thank You !!

6

There are 6 answers

0
Bryan Luby On BEST ANSWER

The artistsQuery convenience constructor does not sort and group by album. artistsQuery returns an array of media item collections of all artists sorted alphabetically by artist name. Nested inside each artist collection is an array of media items associated with all songs for that artist. The nested array is sorted alphabetically by song title.

One way to keep a count of albums by artist is to enumerate through all the song items for each artist collection and use a NSMutableSet to keep track of distinct album titles associated with each song. Then add the count of the set as the value for each artist key in a NSMutableDictionary. Any duplicate album titles will not be added since a NSMutableSet will only take distinct objects:

MPMediaQuery *artistQuery = [MPMediaQuery artistsQuery];
NSArray *songsByArtist = [artistQuery collections];
NSMutableDictionary *artistDictionary = [NSMutableDictionary dictionary];
NSMutableSet *tempSet = [NSMutableSet set];

[songsByArtist enumerateObjectsUsingBlock:^(MPMediaItemCollection *artistCollection, NSUInteger idx, BOOL *stop) {
    NSString *artistName = [[artistCollection representativeItem] valueForProperty:MPMediaItemPropertyArtist];

    [[artistCollection items] enumerateObjectsUsingBlock:^(MPMediaItem *songItem, NSUInteger idx, BOOL *stop) {
        NSString *albumName = [songItem valueForProperty:MPMediaItemPropertyAlbumTitle];
        [tempSet addObject:albumName];
    }];
    [artistDictionary setValue:[NSNumber numberWithUnsignedInteger:[tempSet count]] 
                        forKey:artistName];
    [tempSet removeAllObjects];
}];
NSLog(@"Artist Album Count Dictionary: %@", artistDictionary);

It would be cleaner if you change the query to albumsQuery. This query groups and sorts the collection by album name. Then it is just a matter of enumerating through the array of album collections and keeping a count of the representative artist name for each album in a NSCountedSet. The counted set will track the number of times objects are inserted:

MPMediaQuery *albumQuery = [MPMediaQuery albumsQuery];
NSArray *albumCollection = [albumQuery collections];
NSCountedSet *artistAlbumCounter = [NSCountedSet set];

[albumCollection enumerateObjectsUsingBlock:^(MPMediaItemCollection *album, NSUInteger idx, BOOL *stop) {
    NSString *artistName = [[album representativeItem] valueForProperty:MPMediaItemPropertyArtist];
    [artistAlbumCounter addObject:artistName];
}];
NSLog(@"Artist Album Counted Set: %@", artistAlbumCounter);

You can also retrieve the count for a given object in a NSCountedSet with the countForObject: method.

0
Saad On
1
Rinat Abidullin On

I get number of albums and songs for artist using predicate:

MPMediaPropertyPredicate *artistNamePredicate = [MPMediaPropertyPredicate predicateWithValue:@"ArtistName" forProperty:MPMediaItemPropertyArtist];
MPMediaQuery *myComplexQuery = [[MPMediaQuery alloc] init];
[myComplexQuery addFilterPredicate: artistNamePredicate];
NSInteger songCount = [[myComplexQuery collections] count]; //number of songs
myComplexQuery.groupingType = MPMediaGroupingAlbum;
NSInteger albumCount = [[myComplexQuery collections] count]; //number of albums
0
robinuk On

Thanks Tim E, I couldn't get your code to work first time, but I modded it to this and it works now.

    let artistQuery = MPMediaQuery.artistsQuery()
    artistQuery.groupingType = MPMediaGrouping.AlbumArtist

    let songsByArtist = artistQuery.collections! as NSArray
    let artistDictionary = NSMutableDictionary()
    let tempSet = NSMutableSet()

    songsByArtist.enumerateObjectsUsingBlock( { (artistCollection, idx, stop) -> Void in
        let collection = artistCollection as! MPMediaItemCollection
        let rowItem = collection.representativeItem

        let artistName = rowItem?.valueForProperty(MPMediaItemPropertyAlbumArtist)

        let collectionContent:NSArray = collection.items

        collectionContent.enumerateObjectsUsingBlock({ (songItem, idx, stop) -> Void in
            let item = songItem as! MPMediaItem

            let albumName = item.valueForProperty(MPMediaItemPropertyAlbumTitle)
            tempSet.addObject(albumName!)
        })

        artistDictionary.setValue(NSNumber(unsignedInteger: UInt(tempSet.count)), forKey: artistName! as! String)
        tempSet.removeAllObjects()
    })

    print("Album Count Dictionary: \(artistDictionary)") 
0
Abdul Yasin On

Sorry for late answer.

Posting my answer in case it is helpful to someone.

Below code gets all artists group by album artist and get its all Albums and songs inside the album.

    /// Get all artists and their songs
///
func getAllArtists() {
    let query: MPMediaQuery = MPMediaQuery.artists()
    query.groupingType = .albumArtist

    let artistsColelctions = query.collections

    artists.removeAll()


    var tempSet = NSMutableSet()



    guard artistsColelctions != nil else {
        return
    }

    // 1. Create Artist Objects from collection

    for collection in artistsColelctions! {
        let item: MPMediaItem? = collection.representativeItem

        var artistName = item?.value(forKey: MPMediaItemPropertyArtist) as? String ?? "<Unknown>"
        artistName = artistName.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines)
        let artistId = item!.value(forProperty: MPMediaItemPropertyArtistPersistentID) as! NSNumber


        // temp
        let albumName = item?.albumTitle
        let albumID  = item?.albumPersistentID

        print(albumName)
        print(albumID)



        // Create artist item

        let artist = Artist()
        artist.name = artistName
        artist.artworkTitle = String(artistName.characters.prefix(1)).uppercased()
        artist.artistId = String(describing: artistId)


        // 2. Get Albums for respective Artist object
        //--------------------------------------------

        let mediaQuery2 = MPMediaQuery.albums()
        let predicate2 = MPMediaPropertyPredicate.init(value: artistId, forProperty: MPMediaItemPropertyArtistPersistentID)
        mediaQuery2.addFilterPredicate(predicate2)

        let albums = mediaQuery2.collections

        for collection in albums! {
            let item: MPMediaItem? = collection.representativeItem

            let albumName = item?.value(forKey: MPMediaItemPropertyAlbumTitle) as? String ?? "<Unknown>"
            let albumId = item!.value(forProperty: MPMediaItemPropertyAlbumPersistentID) as! NSNumber
            let artistName = item?.value(forKey: MPMediaItemPropertyAlbumArtist) as? String ?? "unknown"

            let genreName = item?.genre ?? ""

            let year = item?.releaseDate ?? item?.dateAdded

            let dateAdded = item?.dateAdded

            // Create album object

            let album = Album()
            album.name = albumName
            album.artistName = artistName
            album.genre = genreName
            album.releaseDate = year
            album.dateAdded = dateAdded
            album.albumId = String(describing: albumId)

            // Add artwork to album object
            let artwork = Artwork.init(forAlbum: item)
            album.artwork = artwork


            // 3. Get Songs inside the resepctive Album object
            //---------------------------------------------------

            let mediaQuery = MPMediaQuery.songs()
            let predicate = MPMediaPropertyPredicate.init(value: albumId, forProperty: MPMediaItemPropertyAlbumPersistentID)
            mediaQuery.addFilterPredicate(predicate)
            let song = mediaQuery.items

            if let allSongs = song {
                var index = 0

                for item in allSongs {
                    let pathURL: URL? = item.value(forProperty: MPMediaItemPropertyAssetURL) as? URL
                    let isCloud = item.value(forProperty: MPMediaItemPropertyIsCloudItem) as! Bool

                    let trackInfo = TrackInfo()
                    trackInfo.index = index
                    trackInfo.mediaItem = item
                    trackInfo.isCloudItem = isCloud

                    trackInfo.isExplicitItem = item.isExplicitItem

                    trackInfo.isSelected = false
                    trackInfo.songURL = pathURL
                    album.songs?.append(trackInfo)
                    index += 1
                }
            }


            artist.albums?.append(album)

        }

        // Finally add the artist object to Artists Array
        artists.append(artist)

        }


    }
0
evenwerk On

Swift 2 translation of Bryan's answer:

var artistQuery = MPMediaQuery.artistsQuery()
var artistQuery.groupingType = MPMediaGrouping.AlbumArtist
var songsByArtist = artistQuery.collections
var artistDictionary = NSMutableDictionary()
var tempSet = NSMutableSet()

songsByArtist.enumerateObjectsUsingBlock { (artistCollection, idx, stop) -> Void in
     let collection = artistCollection as! MPMediaItemCollection
     let rowItem = collection.representativeItem

     let artistName = rowItem?.valueForProperty(MPMediaItemPropertyAlbumArtist)

     let collectionContent:NSArray = collection.items

     collectionContent.enumerateObjectsUsingBlock { (songItem, idx, stop) -> Void in
          let item = songItem as! MPMediaItem

          let albumName = item.valueForProperty(MPMediaItemPropertyAlbumTitle)
          self.tempSet.addObject(albumName!)
     }

     self.artistDictionary.setValue(NSNumber(unsignedInteger: self.tempSet.count), forKey: artistName! as! String)
     self.tempSet.removeAllObjects()
}
print("Album Count Dictionary: \(artistDictionary)")