-
Integra MusicKit en tu app
Incorpora todo el potencial de Apple Music a tu app con MusicKit. Abordaremos la autorización, la verificación del estado de la suscripción, la selección de música, el control de reproducción y el intercambio de canciones entre tiendas. Aprende a usar el nuevo Music Picker para que los usuarios puedan explorar el catálogo de Apple Music y sus bibliotecas personales. También analizaremos las diferencias entre SystemMusicPlayer y ApplicationMusicPlayer, y te mostraremos cómo consultar el estado de reproducción.
Capítulos
- 0:00 - Introducción
- 2:11 - Configuración y autorización del proyecto
- 7:10 - Elementos musicales y el selector de música
- 10:54 - Reproductores de música y reproducción
- 16:26 - Solicitudes de catálogo
- 20:11 - Próximos pasos
Recursos
Videos relacionados
WWDC23
WWDC22
-
Buscar este video…
-
-
4:47 - Presents the Apple Music subscription offer
@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) } -
5:59 - Adds subscription button to main view
@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 } } } -
8:48 - Add .musicPicker() modifier
@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 } } -
14:49 - Artwork
@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) } } } -
15:06 - Current entry info
@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) } } } } -
15:14 - Playback controls (play, pause)
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() } } } } -
15:38 - Playback controls (next, previous)
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() } } } } -
18:58 - Music catalog resource request
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 return response.item(for: songID) } return (featuredSong, others) }
-