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 })
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!