Integrate MusicKit into your app
App Store & Distribution 进阶 21m

将 MusicKit 整合到你的 App 中

Integrate MusicKit into your app

2026年6月10日

在 Apple 官方观看视频

一句话判断

✅ MusicKit 终于把授权、选歌、播放和订阅转化打磨成了一套极其顺滑的 SwiftUI 原生体验,非音乐类 App 接入 Apple Music 的门槛降到了历史最低。

这场 Session 讲了什么

这场 Session 最值得关注的一件事是:Apple 把 MusicKit 从一个“给纯音乐 App 用的底层 API”变成了“任何 App 都能轻松调用的 SwiftUI 插件”。以前你要在 App 里加个“健身时听 Apple Music”的功能,得自己写授权逻辑、判断订阅状态、手搓选歌列表、处理播放队列,现在全被 .musicPicker.musicSubscriptionOffer 这两个 View Modifier 包圆了。

Apple 这次明确划分了 SystemMusicPlayer(系统播放器)和 ApplicationMusicPlayer(应用内播放器)的边界,并补齐了异步状态监听的短板。这对健身、冥想、游戏或者社交类 App 影响最大,你不再需要为了加个 BGM 功能去重写半个 App,几行代码就能拉起原生的选歌和订阅 UI,甚至还能通过 Apple Services Performance Partner Program 拿订阅佣金。

值得深挖的点

.musicPicker 与订阅转化的商业闭环

Apple 这次主推的 .musicPicker.musicSubscriptionOffer 表面上是 UI 组件,背后其实是 Apple Music 拉新的商业阳谋。以前开发者不愿意接 Apple Music,因为非订阅用户只能听本地库,体验割裂,开发者还得自己写引导订阅的 UI。现在 Apple 直接提供了原生的订阅弹窗,通过 MusicSubscriptionOffer.Options 配置 messageIdentifier(比如 .playMusic),用户不用离开你的 App 就能完成订阅。

这里的 trade-off 很明显:你失去了对选歌和订阅 UI 的绝对控制权,必须用 Apple 的原生样式。但换来的是极高的用户信任度、免审核的 UI 以及实打实的佣金收入。对于非纯音乐类 App 来说,用原生组件绝对比自己手搓一套半吊子 UI 转化率高得多。配合 MusicSubscription.subscriptionUpdates 这个 AsyncSequence,你可以实时监听用户在弹窗里完成订阅的动作,无缝衔接播放逻辑,体验非常丝滑。

SystemMusicPlayer vs ApplicationMusicPlayer 的生死抉择

Session 里花了不少篇幅讲这两个播放器,很多新手在这里栽过跟头。SystemMusicPlayer 是系统的“遥控器”,它控制的是系统的 Music App,App 退到后台或者被杀进程,音乐照样播,锁屏控制中心也能完美接管。但代价是,你只能往队列里塞东西,拿不到完整的队列内容,也做不了复杂的队列操作。

ApplicationMusicPlayer 则是你的 App 自己在发声。你可以完全读写队列、监听每一首歌的播放进度。但坑在于,如果你用它,必须在 Xcode 的 Signing & Capabilities 里勾选 Background Modes 下的 “Audio, AirPlay, and Picture in Picture”,否则 App 一退到后台音乐就断了。另外,Session 里提到的 prepareToPlay() 是个容易被忽略的神仙 API,在用户点击播放前预先缓冲音频资产,能显著消除点击播放按钮后那让人烦躁的半秒钟延迟。

代码片段

1. 优雅处理订阅状态与转化 UI

场景:在主页展示订阅按钮,仅对未订阅用户显示,并监听订阅状态变化。

@State var subscription: MusicSubscription?
@State var showSubscriptionOffer = false

// 配置订阅弹窗选项,指定场景为播放音乐
let options = MusicSubscriptionOffer.Options(messageIdentifier: .playMusic)

var body: some View {
    VStack {
        // 只有当用户有资格订阅时才显示按钮
        if let subscription, subscription.canBecomeSubscriber {
            Button("订阅 Apple Music") {
                showSubscriptionOffer = true
            }
            // 挂载原生订阅弹窗
            .musicSubscriptionOffer(isPresented: $showSubscriptionOffer, options: options)
        }
    }
    // 使用 AsyncSequence 实时监听订阅状态变化
    .task {
        self.subscription = try? await MusicSubscription.current
        for await updatedSubscription in MusicSubscription.subscriptionUpdates {
            self.subscription = updatedSubscription
        }
    }
}

坑:别忘了在 Xcode 的 Info.plist 里配置 NSAppleMusicUsageDescription,否则请求授权时会直接 Crash。

2. 使用原生音乐选择器

场景:让用户从 Apple Music 目录或本地资料库中挑选多首歌曲。

@State var showMusicPicker = false
// 使用数组支持多选,如果是单选则用 Song?
@State var selectedSongs: [Song] = []

var body: some View {
    Button("选择 workout 音乐") {
        showMusicPicker = true
    }
    // 呼出原生音乐选择器
    .musicPicker(isPresented: $showMusicPicker, selection: $selectedSongs)
}

坑:.musicPicker 不需要用户有 Apple Music 订阅也能用,但未订阅用户只能看到并选择他们本地资料库(Local Library)里的歌。

3. 应用内播放控制与状态观察

场景:使用 ApplicationMusicPlayer 播放选中的歌曲,并构建播放/暂停控制 UI。

let player = ApplicationMusicPlayer.shared
@State var state = ApplicationMusicPlayer.shared.state

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

var playPauseButton: some View {
    Button(isPlaying ? "暂停" : "播放", systemImage: isPlaying ? "pause.fill" : "play.fill") {
        if isPlaying {
            player.pause()
        } else {
            Task {
                // 播放前预缓冲,减少首帧延迟
                try await player.prepareToPlay()
                try await player.play()
            }
        }
    }
}

坑:使用 ApplicationMusicPlayer 必须在 Xcode 开启 Background Modes -> Audio,否则切到后台立刻静音。

最佳实践

对于已有项目,如果你之前用 MPMediaPickerController 或者自己写了一套 Apple Music API 的请求和选歌逻辑,强烈建议迁移到 .musicPicker。这能帮你砍掉成百上千行的 UI 和数据解析代码,把精力放回业务本身。

新项目接入时,优先明确你的 App 是“音乐播放器”还是“需要 BGM 的工具”。如果是后者(比如健身、番茄钟),无脑选择 ApplicationMusicPlayer,自己掌控队列和播放时机;如果是前者(比如独立的音乐客户端),使用 SystemMusicPlayer 能帮你省去处理锁屏控制中心和后台音频中断的麻烦。

实战中最容易踩的坑是网络延迟导致的播放卡顿。在构建播放队列时,尽量使用容器类型(如 AlbumPlaylist)的特殊队列初始化方法,MusicKit 会在底层做延迟加载(Lazy loading),这比把几百首 Song 塞进数组里再传给 Player 要快得多。

还有什么值得关注

  • 跨区内容等效MusicCatalogResourceRequest 新增了 .findEquivalents 选项,当请求的特定歌曲在用户所在区服不可用时,自动返回等效的替代版本,避免开天窗。
  • 异步状态监听MusicSubscription.subscriptionUpdates 和播放器的状态都全面拥抱了 Swift Concurrency,用 for await 监听状态变化比以前的 Combine 或 Delegate 模式清爽太多。
  • Artwork 渲染优化ArtworkImage 组件现在能更好地处理占位图和圆角,配合 .quaternary 颜色做骨架屏过渡非常自然。
MusicKit SwiftUI SystemMusicPlayer MusicPicker Apple Music