You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVFoundation音频播放器仅停止时响应滑块音量,如何实现拖拽实时调整?

解决方案

核心原因

  • 音量赋值逻辑仅在播放触发时执行一次,滑块滑动过程中没有同步更新AVAudioPlayer的volume属性
  • 原有播放、停止方法每次执行都重复初始化播放器实例,属于冗余逻辑,也会干扰音量实时生效

修改方案

  1. 给Slider添加数值变化监听回调,每次滑块值变动时直接更新正在运行的播放器音量
  2. 优化播放器初始化逻辑,避免每次播放/停止重复创建实例

修改后的完整代码如下:

import SwiftUI
import AVFoundation

var campFirePlayer: AVAudioPlayer!
var campFireIsTapped: Bool = false

struct CF_RowView: View {
    
    @State var SFname: String
    @State var nameOfSound: String
    @State var urlOfSound: String
    @State var slidervalue: Float
    
    var body: some View {
        HStack {
            Image(systemName: SFname)
                .frame(width: 20)
            
            // 音效开关按钮
            Button(action: {
                campFireIsTapped.toggle()
                campFireIsTapped ? self.playCampFire() : self.stopCampFire()
            }) {
                Text(nameOfSound).frame(width: 150, alignment: .leading)
            }
            .padding(.leading, 10)
            .foregroundColor(Color.primary)
            Spacer()
            // 新增onChange监听滑块数值变化,实时更新音量
            Slider(value: $slidervalue)
                .frame(width: 130, alignment: .trailing)
                .onChange(of: slidervalue) { newValue in
                    guard campFirePlayer != nil, campFireIsTapped else { return }
                    campFirePlayer.volume = newValue
                }
        }.frame(width:320)
    }
    
    // 优化后的播放音效方法,避免重复初始化
    func playCampFire() {
        // 播放器仅初始化一次
        if campFirePlayer == nil {
            let url = Bundle.main.url(forResource: urlOfSound, withExtension: "aif")
            guard let soundUrl = url else { return }
            do {
                campFirePlayer = try AVAudioPlayer(contentsOf: soundUrl)
                campFirePlayer.numberOfLoops = -1
            } catch {
                print("播放器初始化失败:\(error)")
                return
            }
        }
        campFirePlayer.volume = slidervalue
        campFirePlayer.play()
    }
    
    // 优化后的停止音效方法
    func stopCampFire() {
        guard campFirePlayer != nil else { return }
        campFirePlayer.stop()
        // 若需要下次播放从头开始可取消注释下方代码
        // campFirePlayer.currentTime = 0
    }
}

兼容说明

如果需要适配iOS13及以下不支持onChange的系统版本,可以将滑块的Binding替换为自定义setter,或者使用Combine框架监听slidervalue的数值变化,实现逻辑一致。


内容的提问来源于stack exchange,提问作者Shannon Slater

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 00:45:06