Book

Exploring MusicKit and Apple Music API

Unlock the full power of MusicKit & Apple Music APIs in your apps with the best guide! Use code musickit-blog for a limited-time 35% discount!

Suppose you are using MusicKit and want to work with updating the user’s playlists. In that case, you quickly realize there is no way to differentiate the playlists that are user created and editable vs. those made by Apple that cannot be edited.

Using the library request and the new MusicLibrary class to add tracks to a playlist, this is what you may start with:

var request = MusicLibraryRequest<Playlist>()
equest.sort(by: \.lastPlayedDate, ascending: false)

let response = try await request.response()

guard let playlist = response.items.first else { return }

try await MusicLibrary.shared.add(track, to: playlist)

If you try to add a track to a playlist created by Apple, then you end up with a similar error as shown below:

Error Domain=MPErrorDomain Code=5 "The requested action is not supported" UserInfo={NSLocalizedDescription=The requested action is not supported}

While I have not figured out a native way to implement this using the MusicLibraryRequest, I created my structure and implementation using Apple Music API to achieve the same.

LibraryPlaylist

The first step is to create a LibraryPlaylist structure that has the canEdit property because that’s what you want:

import Foundation
import MusicKit

public typealias LibraryPlaylists = MusicItemCollection<LibraryPlaylist>

public struct LibraryPlaylist: Codable, MusicItem {
  public let id: MusicItemID
  public let attributes: Attributes

  public struct Attributes: Codable, Sendable {
    public let canEdit: Bool
    public let name: String
    public let isPublic: Bool
    public let hasCatalog: Bool
    public let playParams: PlayParameters
    public let description: Description?
    public let artwork: Artwork?
  }

  public struct Description: Codable, Sendable {
    public let standard: String
  }

  public struct PlayParameters: Codable, Sendable {
    public let id: MusicItemID
    public let isLibrary: Bool
    public let globalID: MusicItemID?

    enum CodingKeys: String, CodingKey {
      case id, isLibrary
      case globalID = "globalId"
    }
  }

  public var globalID: String? {
    attributes.playParams.globalID?.rawValue
  }
}

It also has some other properties that you may find useful like isPublic to know if the playlist is private or public and the globalID to get more detail about the playlist from the Apple Music catalog.

Fetching Library Playlists

Then, you fetch the library playlists using the Apple Music API and decode the data as a collection of LibraryPlaylist instead of Playlist:

let libraryPlaylistsURL = URL(string: "https://api.music.apple.com/v1/me/library/playlists")

guard let libraryPlaylistsURL else { return }

let request = MusicDataRequest(urlRequest: URLRequest(url: libraryPlaylistsURL))
let response = try await request.response()
let playlists = try JSONDecoder().decode(LibraryPlaylists.self, from: response.data)

guard let playlist = playlists.first else { return }

print(playlist)
print(playlist.attributes.canEdit)

Filtering the Editable Playlists

I know it is not as good as the native implementation, where you can filter by the last played date or the date added, but at least you can now filter the editable playlists!

let editablePlaylists = playlists.filter { $0.attributes.canEdit }

With this, you now have the user’s editable playlists!

Similarly, you can filter the public playlists:

let publicPlaylists = playlists.filter { $0.attributes.isPublic }

MusadoraKit

If you don’t want to write so much code, you can import MusadoraKit and have a two-liner solution for the above problem that fetches ALL the user’s playlists. However, not that this request will be slow based on the number of playlists.

let playlists: LibraryPlaylists = try await MLibrary.playlists()

let editablePlaylists = MusicItemCollection(playlists.filter { $0.attributes.canEdit })

let publicPlaylists = MusicItemCollection(playlists.filter { $0.attributes.isPublic })
Book

Exploring MusicKit and Apple Music API

Unlock the full power of MusicKit & Apple Music APIs in your apps with the best guide! Use code musickit-blog for a limited-time 35% discount!

Written by

Rudrank Riyam

Hi, my name is Rudrank. I create apps for Apple Platforms while listening to music all day and night. Author of "Exploring MusicKit". Apple WWDC 2019 scholarship winner.