当前位置: 首页 > news >正文

SwiftUI 音频播放器:AVPlayer 在线播放 + 播放进度条 + 音量调节 + 后台播放

在 iOS 应用中,如果你想实现一个简洁优雅的音乐播放器组件,Apple 的 AVPlayer 是一个非常可靠的工具。本文将带你用 SwiftUI 构建一个支持:

✅ 在线音频播放
✅ 实时播放进度条
✅ 音量调节
✅ 后台播放(锁屏仍可播放)

实现效果

下图展示了本文要实现的 SwiftUI 播放器界面:

项目结构预览

我们将实现以下三个主要组件:

  • PlayerViewModel: 音频播放逻辑 + 状态管理
  • PlayerView: 播放器界面(播放按钮、进度条、音量调节)
  • ContentView: 加载一个在线音频 URL 进行播放

1. 创建 PlayerViewModel:播放逻辑核心

我们使用 ObservableObject 管理 AVPlayer 播放器状态,支持实时监听播放进度和音量。

import Foundation
import AVFoundation
import Combine
import SwiftUIclass PlayerViewModel: ObservableObject {@Published var player: AVPlayer                    // 播放器对象@Published var isPlaying = false                   // 是否正在播放@Published var currentTime: Double = 0             // 当前播放时间(秒)@Published var duration: Double = 1                // 音频总时长(秒)@Published var volume: Float = 0.5                 // 音量(0~1)private var timeObserverToken: Any?                // 播放进度监听private var cancellables = Set<AnyCancellable>()   // Combine 订阅集合// 初始化 AVPlayer 并配置监听init(url: URL) {self.player = AVPlayer(url: url)setupObserver()          // 监听播放进度setupVolume()            // 音量变化绑定configureAudioSession()  // 配置后台播放}// 销毁时移除观察者deinit {if let token = timeObserverToken {player.removeTimeObserver(token)}}/// 设置播放进度监听private func setupObserver() {timeObserverToken = player.addPeriodicTimeObserver(forInterval: CMTime(seconds: 0.5, preferredTimescale: 600),queue: .main) { [weak self] time inguard let self = self,let currentItem = self.player.currentItem else { return }self.currentTime = time.secondsself.duration = currentItem.duration.seconds}}/// 音量绑定监听private func setupVolume() {player.volume = volume$volume.sink { [weak self] newVolume inself?.player.volume = newVolume}.store(in: &cancellables)}/// 播放 / 暂停 控制func togglePlayPause() {if isPlaying {player.pause()} else {player.play()}isPlaying.toggle()}/// 拖动进度条跳转到指定时间func seek(to time: Double) {player.seek(to: CMTime(seconds: time, preferredTimescale: 600))}/// 开启后台播放能力private func configureAudioSession() {do {try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default)try AVAudioSession.sharedInstance().setActive(true)} catch {print("Failed to configure audio session: \(error)")}}
}

2. 构建 SwiftUI 播放界面 PlayerView

这个界面包含播放按钮、音量滑块和进度条。

struct PlayerView: View {@StateObject private var viewModel: PlayerViewModel// 接收外部传入的音频 URLinit(url: URL) {_viewModel = StateObject(wrappedValue: PlayerViewModel(url: url))}var body: some View {VStack(spacing: 20) {// 播放 / 暂停 按钮Button(action: {viewModel.togglePlayPause()}) {Image(systemName: viewModel.isPlaying ? "pause.circle.fill" : "play.circle.fill").resizable().frame(width: 80, height: 80)}// 音量调节HStack {Text("音量: \(Int(viewModel.volume * 100))%")Slider(value: Binding(get: { viewModel.volume },set: { viewModel.volume = $0 }),in: 0...1).accentColor(.green).padding(.horizontal)}// 播放进度条HStack {Text("\(formatTime(viewModel.currentTime))")Slider(value: $viewModel.currentTime,in: 0...viewModel.duration,onEditingChanged: { isEditing inif !isEditing {viewModel.seek(to: viewModel.currentTime)}})Text("\(formatTime(viewModel.duration))")}}.padding()}/// 时间格式化工具:转成 mm:ss 格式private func formatTime(_ time: Double) -> String {let minutes = Int(time) / 60let seconds = Int(time) % 60return String(format: "%02d:%02d", minutes, seconds)}
}

3. 在 ContentView 中加载播放器

我们选用一首可用的在线音频地址示例:

struct ContentView: View {let audioURL = URL(string: "https://er-sycdn.kuwo.cn/307531268bf6fddfb4adb34fe9d4c3a3/6805fabb/resource/30106/trackmedia/M500004CJfjo2EGyPZ.mp3")!var body: some View {PlayerView(url: audioURL)}
}

4. 支持后台播放说明 

 通过设置:

try AVAudioSession.sharedInstance().setCategory(.playback)

 在 Info.plist 中添加: 

<key>UIBackgroundModes</key>
<array><string>audio</string>
</array>

即可支持后台音频播放(包括锁屏继续播放)功能。 

相关文章:

  • Python面向对象程序设计
  • FreeRTos学习记录--1.工程创建与源码概述
  • 深度学习预训练和微调
  • WWW2025 快手最新论文 T2Diff 解读:生成式扩散模型+混合注意力打造高效推荐
  • Synopsys:printvar命令和puts/echo命令的区别
  • Vue3---(9)组件间通信
  • 【基于WSAAsyncSelec模型的通信程序设计】
  • 每天学一个 Linux 命令(29):tail
  • JavaScript 中的单例模式
  • 单例模式(线程安全)
  • Uniapp 自定义TabBar + 动态菜单实现教程(Vuex状态管理详解)
  • Nginx详细使用
  • 乐家桌面安卓版2025下载-乐家桌面软件纯净版安装分享码大全
  • buildadmin 自定义单元格渲染
  • AOSP Android14 Launcher3——点击桌面图标启动应用动画流程
  • Docker安装beef-xss
  • Python3网络爬虫开发--爬虫基础
  • 多语言商城系统开发流程
  • 【Easylive】consumes = MediaType.MULTIPART_FORM_DATA_VALUE 与 @RequestPart
  • 【英语语法】词法---连词
  • 在因关税战爆火的敦煌网上,美国人爱买什么中国商品
  • 张文宏:加强基层医疗体系建设,提升传染病早期监测和预警能力
  • 习近平致电祝贺诺沃亚当选连任厄瓜多尔总统
  • 电动自行车新国标将于9月1日落地,首批6家检测机构出炉
  • 人民文学奖颁出,董宇辉获传播贡献奖
  • 老总们带着产品直奔对接会,外贸拓内销找到更多“新路子”