View in English

  • Apple 开发者
    • 入门汇总

    探索“入门汇总”

    • 概览
    • 学习
    • Apple Developer Program

    及时了解最新动态

    • 最新动态
    • 开发者你好
    • 平台

    探索“平台”

    • Apple 平台
    • iOS
    • iPadOS
    • macOS
    • Apple tvOS
    • visionOS
    • watchOS
    • App Store

    精选

    • 设计
    • 分发
    • 游戏
    • 配件
    • 网页
    • Home
    • CarPlay 车载
    • 技术

    探索“技术”

    • 概览
    • Xcode
    • Swift
    • SwiftUI

    精选

    • 辅助功能
    • App Intents
    • Apple 智能
    • 游戏
    • 机器学习与 AI
    • 安全性
    • Xcode Cloud
    • 社区

    探索“社区”

    • 概览
    • “与 Apple 会面交流”活动
    • 社区主导的活动
    • 开发者论坛
    • 开源

    精选

    • WWDC
    • Swift Student Challenge
    • 开发者故事
    • App Store 大奖
    • Apple 设计大奖
    • Apple Developer Centers
    • 文档

    探索“文档”

    • 文档库
    • 技术概述
    • 示例代码
    • 《人机界面指南》
    • 视频

    发布说明

    • 精选更新
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • Apple tvOS
    • Xcode
    • 下载

    探索“下载”

    • 所有下载
    • 操作系统
    • 应用程序
    • 设计资源

    精选

    • Xcode
    • TestFlight
    • 字体
    • SF Symbols
    • Icon Composer
    • 支持

    探索“支持”

    • 概览
    • 帮助指南
    • 开发者论坛
    • “反馈助理”
    • 联系我们

    精选

    • 《开发者账户帮助》
    • 《App 审核指南》
    • 《App Store Connect 帮助》
    • 即将实行的要求
    • 协议和准则
    • 系统状态
  • 快速链接

    • 活动
    • 新闻
    • 论坛
    • 示例代码
    • 视频
 

视频

打开菜单 关闭菜单
  • 专题
  • 所有视频
  • 关于

更多视频

  • 简介
  • 概要
  • 代码
  • 了解 NowPlaying 框架

    抢先了解 NowPlaying——利用这个 Swift 框架,将你 App 的媒体播放搬上锁定屏幕、控制中心、灵动岛和 CarPlay 车载等系统界面。了解如何使用其中的可观察 API 发布播放状态并响应命令。探索远程播放会话,这项新功能可让你的 App 在外部设备上呈现媒体播放,并将完整的播放控件带到同样的系统界面。

    章节

    • 0:00 - Introduction
    • 1:08 - Media sessions
    • 5:03 - Remote media sessions
    • 10:31 - Media sharing extensions

    资源

    • Routing media to third-party devices
    • Publishing remote media sessions
    • Publishing media sessions
    • Setting up a remote notification server
      • 高清视频
      • 标清视频
  • 搜索此视频…
    • 1:57 - Existing PlayerModel implementation

      import Observation
      
      @Observable
      final class PlayerModel {
          let player: SoundPlayer
          var sound: Sound { player.currentSound }
      
          init(player: SoundPlayer) {
              self.player = player
          }
      }
    • 2:06 - Adopt MediaSessionRepresentable

      import NowPlaying
      
      extension PlayerModel: MediaSessionRepresentable {
          var id: String { "ambient-sound-session" }
      
          var content: (any MediaContentRepresentable)? {
              return GenericContent(
                  id: sound.id,
                  title: sound.name,
                  subtitle: sound.description,
                  type: .audio,
                  duration: .live,
                  artwork: Artwork(id: sound.id) { size in
                      let data = try await self.artworkData(size: size)
                      return try ArtworkRepresentation(data: data)
                  }
              )
          }
      
          var playbackSnapshot: MediaPlaybackSnapshot? {
              MediaPlaybackSnapshot(
                  state: player.isPlaying ? .playing() : .paused
              )
          }
      
          var commands: [MediaCommand] {[
              .play { self.player.play() },
              .pause { self.player.pause() },
              .previous { self.player.previous() },
              .next { self.player.next() }
          ]}
      }
    • 4:31 - MediaSession initialization

      import NowPlaying
      
      struct PlayerController {
          let player: SoundPlayer
          let model: PlayerModel
          let session: MediaSession<PlayerModel>
      
          init() {
              self.player = SoundPlayer()
              self.model = PlayerModel(player: player)
              self.session = MediaSession(model)
          }
      }
    • 6:42 - App extension entry point

      import ExtensionFoundation
      import NowPlaying
      
      @main
      final class SampleAppExtension: @MainActor RemoteMediaSessionExtension {
          var configuration: some AppExtensionConfiguration {
              RemoteMediaSessionExtensionConfiguration(extension: self)
          }
      
          var extensionPoint: AppExtensionPoint {
              AppExtensionPoint.Identifier(host: "com.apple.nowplaying", name: "remote-media")
          }
      
          func session(_ state: RemotePlayerState) async throws -> RemotePlayerModel {
              RemotePlayerModel(state: state)
          }
      }
    • 7:23 - Existing RemotePlayerModel implementation

      import Observation
      
      @Observable
      @MainActor
      final class RemotePlayerModel {
          let client: ServerClient
          var state: RemotePlayerState
      
          init(state: RemotePlayerState) {
              self.client = ServerClient(sessionID: state.sessionID)
              self.state = state
          }
      }
    • 7:40 - Adopt RemoteMediaSessionRepresentable in app extension

      import NowPlaying
      
      extension RemotePlayerModel: @MainActor RemoteMediaSessionRepresentable {
          var id: String { state.sessionID }
      
          var content: (any MediaContentRepresentable)? {
              GenericContent(
                  id: state.sound.id,
                  title: state.sound.name,
                  subtitle: state.sound.description,
                  type: .audio,
                  duration: .live,
                  artwork: Artwork(id: state.sound.id) { size in
                      let data = try await self.artworkData(size: size)
                      return try ArtworkRepresentation(data: data)
                  }
              )
          }
      
          var playbackSnapshot: MediaPlaybackSnapshot? {
              MediaPlaybackSnapshot(
                  state: state.isPlaying ? .playing() : .paused
              )
          }
      
          var commands: [MediaCommand] {[
              .play { try await self.client.send(.play) },
              .pause { try await self.client.send(.pause) },
              .previous { try await self.client.send(.previous) },
              .next { try await self.client.send(.next) }
          ]}
      
          var devices: [MediaDevice] {
              state.devices.map { device in
                  MediaDevice(
                      id: device.id,
                      name: device.name,
                      type: .speaker,
                      capabilities: [
                          .absoluteVolume(device.volume) { volume in
                              // send volume change to server
                          }
                      ]
                  )
              }
          }
      
          func update(_ state: RemotePlayerState) {
              self.state = state
          }
      }
    • 0:00 - Introduction
    • Discover the Now Playing system experience, available across all Apple platforms. It allows apps to surface currently playing media info on system surfaces like the Lock Screen, Dynamic Island, and CarPlay.

    • 1:08 - Media sessions
    • Learn how to use the media sessions API to bring audio or video from your app into the system's Now Playing experience by adopting the MediaSessionRepresentable protocol.

    • 5:03 - Remote media sessions
    • Discover how to extend playback control to devices like smart speakers by adopting RemoteMediaSessionRepresentable and utilizing Apple Push Notification service (APNs).

    • 10:31 - Media sharing extensions
    • Find out how Media Sharing Extensions simplify routing media from iPhone to other devices by leveraging the system device picker without needing to embed additional SDKs.

Developer Footer

  • 视频
  • WWDC26
  • 了解 NowPlaying 框架
  • 打开菜单 关闭菜单
    • iOS
    • iPadOS
    • macOS
    • Apple tvOS
    • visionOS
    • watchOS
    打开菜单 关闭菜单
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    打开菜单 关闭菜单
    • 辅助功能
    • 配件
    • Apple 智能
    • App 扩展
    • App Store
    • 音频与视频 (英文)
    • 增强现实
    • 设计
    • 分发
    • 教育
    • 字体 (英文)
    • 游戏
    • 健康与健身
    • App 内购买项目
    • 本地化
    • 地图与位置
    • 机器学习与 AI
    • 开源资源 (英文)
    • 安全性
    • Safari 浏览器与网页 (英文)
    打开菜单 关闭菜单
    • 完整文档 (英文)
    • 部分主题文档 (简体中文)
    • 教程
    • 下载
    • 论坛 (英文)
    • 视频
    打开菜单 关闭菜单
    • 支持文档
    • 联系我们
    • 错误报告
    • 系统状态 (英文)
    打开菜单 关闭菜单
    • Apple 开发者
    • App Store Connect
    • 证书、标识符和描述文件 (英文)
    • 反馈助理
    打开菜单 关闭菜单
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program (英文)
    • Mini Apps Partner Program
    • News Partner Program (英文)
    • Video Partner Program (英文)
    • 安全赏金计划 (英文)
    • Security Research Device Program (英文)
    打开菜单 关闭菜单
    • 与 Apple 会面交流
    • Apple Developer Center
    • App Store 大奖 (英文)
    • Apple 设计大奖
    • Apple Developer Academies (英文)
    • WWDC
    阅读最近新闻。
    获取 Apple Developer App。
    版权所有 © 2026 Apple Inc. 保留所有权利。
    使用条款 隐私政策 协议和准则