Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2026 SwiftAudio & Video

WWDC26 · 21 min · Swift / Audio & Video

Integrate MusicKit into your app

Bring the power of Apple Music into your app using MusicKit. We’ll cover authorization, subscription-status checks, music selection, playback control, and cross-storefront song sharing. Learn how to use the new Music Picker to let people browse the Apple Music catalog and their personal libraries. We’ll also break down the differences between SystemMusicPlayer and ApplicationMusicPlayer, and show you how to observe playback state.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 8 snippets

Presents the Apple Music subscription offer swift · at 4:47 ↗
@State var showSubscriptionOffer = false

let options = MusicSubscriptionOffer.Options(
    messageIdentifier: .playMusic
)

@ViewBuilder
var musicSubsriptionButton: some View {
    Button("Subscribe to Apple Music", systemImage: "music.note") {
        showSubscriptionOffer = true
    }
    .musicSubscriptionOffer(isPresented: $showSubscriptionOffer, options: options)
}
Adds subscription button to main view swift · at 5:59 ↗
@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
        }
    }
}
Add .musicPicker() modifier swift · at 8:48 ↗
@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)
}

var body: some View {
    VStack {
        if let subscription, subscription.canBecomeSubscriber {
            musicSubscriptionButton
        }
        musicPickerButton
    }
}
Artwork swift · at 14:49 ↗
@State var queue = ApplicationMusicPlayer.shared.queue

var body: some View {
    VStack {
        if let artwork = queue.currentEntry?.artwork {
            ArtworkImage(artwork, width: 200, height: 200)
        } else {
            // Placeholder artwork
            RoundedRectangle(cornerRadius: 16)
                .fill(.quaternary)
                .frame(width: 200, height: 200)
        }
    }
}
Current entry info swift · at 15:06 ↗
@State var queue = ApplicationMusicPlayer.shared.queue

var body: some View {
    VStack {
        // ...
        if let currentSong = queue.currentEntry {
            Text(currentSong.title)
                .font(.title3.bold())
              
            if let subtitle = currentSong.subtitle {
                Text(subtitle)
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
            }
        }
    }
}
Playback controls (play, pause) swift · at 15:14 ↗
let player = ApplicationMusicPlayer.shared
@State var state = ApplicationMusicPlayer.shared.state

var isPlaying: Bool {
    state.playbackStatus == .playing
}

var playPause: some View {
    Button (
        isPlaying ? "Pause": "Play",
        systemImage: isplaying ? "pause.fill" : "play.fill"
    ) {
        if isPlaying {
            player.pause()
        } else {
            Task {
                try await player.play()
            }
        }
    }
}
Playback controls (next, previous) swift · at 15:38 ↗
let player = ApplicationMusicPlayer.shared

var controls: some View {
    HStack {
        Button("Back", systemImage: "backward.fill") {
            Task {
                try await player.skipToPreviousEntry()
            }
        }
        // ...
        Button("Next", systemImage: "forward.fill") {
            Task {
                try await player.skipToNextEntry()
            }
        }
    }
}
Music catalog resource request swift · at 18:58 ↗
func fetchSongs(songIDs: [MusicItemID]) async throws -> (featured: Song?, other: [Song]) {
    var request = MusicCatalogResourceRequestSong>(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
        return response.item(for: songID)
    }
    
    return (featuredSong, others)
}

Resources