Integrate MusicKit into your app
Use MusicKit to authorize music access, present subscription offers, pick Apple Music or library content, control playback, and fetch catalog songs.
TL;DR
- Configure MusicKit by enabling the MusicKit service for the App ID, adding the Media Library capability in Xcode, and requesting
MusicAuthorizationbefore accessing music content. - Use
.musicSubscriptionOfferwithMusicSubscription.currentandMusicSubscription.subscriptionUpdatesto show an in-app Apple Music offer only when a person can become a subscriber. - Use the SwiftUI
.musicPickermodifier to selectSongvalues from a unified Apple Music catalog and library UI; without a subscription, it shows only the person's library. - Choose between
SystemMusicPlayerandApplicationMusicPlayer, build playback UI from observable player state and queue data, and useMusicCatalogResourceRequestwith.findEquivalentsfor storefront-aware catalog content.
Project setup, authorization, and subscription state
MusicKit is a Swift framework for Apple platforms that integrates with Swift concurrency and SwiftUI. To make MusicKit requests, the app needs a developer token. The session shows the automatic-token path: enable the MusicKit checkbox for the app's App ID in the developer portal, then make sure Xcode is signed into the same developer account.
Before browsing or playing a person's music content, request access with MusicAuthorization.request(). Add the Media Library capability in Xcode and provide a usage description; that text appears in the MusicKit permission alert.
An Apple Music subscription is not required for MusicKit, but without one the app can access only purchased or synced music. If the person can become a subscriber, present an in-app subscription offer using .musicSubscriptionOffer and keep subscription state current with MusicSubscription.current and MusicSubscription.subscriptionUpdates.
- Enable MusicKit for the App ID in App Services so developer tokens can be generated automatically.
- Add the Media Library capability and describe why the app needs access to music content.
- Use
MusicSubscription.canBecomeSubscriberto decide whether to show a subscription button. MusicSubscriptionOffer.Optionscan include partner-program information and amessageIdentifier, such as.playMusic.
Present an Apple Music subscription offer
Shows the in-app Apple Music subscription UI with a message tailored for playing music.
@State var showSubscriptionOffer = false
let options = MusicSubscriptionOffer.Options(
messageIdentifier: .playMusic
)
@ViewBuilder var musicSubscriptionButton: some View {
Button("Subscribe to Apple Music", systemImage: "music.note") {
showSubscriptionOffer = true
}
.musicSubscriptionOffer(isPresented: $showSubscriptionOffer, options: options)
}Track subscription updates
Fetches the current subscription and listens for changes after authorization.
@State var subscription: MusicSubscription?
var body: some View {
VStack {
if let subscription, subscription.canBecomeSubscriber {
musicSubscriptionButton
}
}
.task(id: isAuthorized) {
self.subscription = try? await MusicSubscription.current
for await subscription in MusicSubscription.subscriptionUpdates {
self.subscription = subscription
}
}
}Music items and Music Picker
MusicKit models content as music items. Items such as Album, Song, Genre, Station, and Playlist are value types with attributes, relationships, and associations. Attributes are direct properties like an album title or content rating; relationships describe strongly related content such as an album's tracks; associations describe related content with weaker ties, such as other versions of an album.
The Music Picker is exposed as a SwiftUI view modifier and presents a unified interface for the Apple Music catalog and the person's library. If the person does not have an Apple Music subscription, the picker is still usable, but it shows library items rather than both library and catalog content.
The picker can bind to a single selected item or to an array for multi-selection. It can also select container content such as albums or playlists from their detail pages.
- Use
.musicPicker(isPresented:selection:)to present the picker from any SwiftUI view. - Bind selection to
Song?for a single song or to an array for multiple selections. - The picker handles browsing and search across supported MusicKit content sources.
- Subscription status affects catalog availability, not whether the picker itself can be shown.
Add a Music Picker for a song
Presents the Music Picker and stores the selected Song in SwiftUI state.
@State var showMusicPicker = false
@State var selectedSong: Song? = nil
@ViewBuilder var musicPickerButton: some View {
Button("Pick some Music", systemImage: "music.note.list") {
showMusicPicker = true
}
.musicPicker(isPresented: $showMusicPicker, selection: $selectedSong)
}Players, queues, and playback behavior
MusicKit provides SystemMusicPlayer and ApplicationMusicPlayer, both subclasses of MusicPlayer. SystemMusicPlayer controls the system Music app: apps can set its queue, but cannot inspect the full queue beyond the current item. ApplicationMusicPlayer plays from within the app and gives full read/write access to its queue.
Both players support playback state such as repeat and shuffle, and both can control whether playback affects the Music app's listening history through affectsListeningHistory. By default, playback generally appears in Recently Played, while respecting the Music app's Use Listening History setting.
SystemMusicPlayer continues playing if the app backgrounds or quits because it controls the system Music app. To get comparable background playback with ApplicationMusicPlayer, enable the Audio Background Mode capability.
- Create queues from playable items such as songs, albums, and playlists.
- Use special queue initializers for container types to lazily load their contents.
- Call
prepareToPlay()when upcoming content is known to reduce delay before audible playback. - Call
play()to start andpause()to stop playback. - Observe player state and queue objects directly in SwiftUI for playback UI.
Building playback UI in SwiftUI
The workout app UI reads ApplicationMusicPlayer.shared.queue to display the current entry's artwork, title, and subtitle. ArtworkImage renders MusicKit artwork when available, while a placeholder can cover the empty state.
Playback controls derive their state from ApplicationMusicPlayer.shared.state. The play/pause button checks playbackStatus, calls pause() when already playing, and otherwise calls async play(). Previous and next controls call async skip methods on the player.
- Use
queue.currentEntry?.artworkwithArtworkImagefor now-playing artwork. - Use
queue.currentEntry?.titleand optionalsubtitlefor now-playing labels. - Use
state.playbackStatus == .playingto derive play/pause UI. - Use
skipToPreviousEntry()andskipToNextEntry()for transport controls.
Display current artwork and song information
Uses the application player queue as the source of truth for now-playing artwork and metadata.
@State var queue = ApplicationMusicPlayer.shared.queue
var body: some View {
VStack {
if let artwork = queue.currentEntry?.artwork {
ArtworkImage(artwork, width: 200, height: 200)
} else {
RoundedRectangle(cornerRadius: 16)
.fill(.quaternary)
.frame(width: 200, height: 200)
}
if let currentSong = queue.currentEntry {
Text(currentSong.title)
.font(.title3.bold())
if let subtitle = currentSong.subtitle {
Text(subtitle)
.font(.subheadline)
.foregroundStyle(.secondary)
}
}
}
}Play, pause, previous, and next controls
Builds simple transport controls around ApplicationMusicPlayer state and async player operations.
let player = ApplicationMusicPlayer.shared
@State var state = ApplicationMusicPlayer.shared.state
var isPlaying: Bool {
state.playbackStatus == .playing
}
var controls: some View {
HStack {
Button("Back", systemImage: "backward.fill") {
Task { try await player.skipToPreviousEntry() }
}
Button(isPlaying ? "Pause" : "Play",
systemImage: isPlaying ? "pause.fill" : "play.fill") {
if isPlaying {
player.pause()
} else {
Task { try await player.play() }
}
}
Button("Next", systemImage: "forward.fill") {
Task { try await player.skipToNextEntry() }
}
}
}Catalog requests and storefront equivalency
Catalog requests let an app query Apple Music independently of the person's library, which is useful for curated shelves or quick-start recommendations. MusicCatalogResourceRequest is a structured request for a specific resource type, such as Song. Requests can configure options, requested relationships and associations, and result limits.
Calling async response() returns a MusicCatalogResourceResponse with strongly typed results in a MusicItemCollection. Collections support pagination: when hasNextBatch is true, fetch more items with async nextBatch().
Resource availability can vary by account settings, storefront, region, and explicit-content restrictions. A requested resource may have an equivalent item with a different ID in another region, or a clean equivalent when explicit content is unavailable. The .findEquivalents option enables that equivalency behavior, and callers should handle missing results because the catalog is not guaranteed to return every requested item.
- Use structured catalog requests for Apple Music API content in MusicKit.
- Use
matching: \.id, memberOf: idsto request specific known catalog IDs. - Use
.findEquivalentsfor cross-storefront or content-restriction equivalents. - Use
response.item(for:)to retrieve the returned item corresponding to an input ID. - Always handle unavailable catalog resources.
Fetch songs by catalog IDs with equivalency
Requests a set of songs, allows storefront/content equivalents, and safely maps returned items back to requested IDs.
func fetchSongs(songIDs: [MusicItemID]) async throws -> (featured: Song?, other: [Song]) {
var request = MusicCatalogResourceRequest<Song>(matching: \.id, memberOf: songIDs)
request.options = [.findEquivalents]
let response = try await request.response()
let featuredSongID = songIDs[0]
let featuredSong = response.item(for: featuredSongID)
let others: [Song] = songIDs[1...].compactMap { songID in
response.item(for: songID)
}
return (featuredSong, others)
}Resources
Related Sessions
- Discover Observation in SwiftUI
- Explore more content with MusicKit
- Meet Apple Music API and MusicKit
Meet the Music Understanding framework
Use MusicUnderstandingSession to analyze audio on device for key, rhythm, structure, pace, instrument activity, and loudness across Apple platforms.
Discover generated subtitles and subtitle styles
Use on-device generated subtitles and subtitle style preview to improve AVKit/AVFoundation video accessibility across Apple platforms.