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

SwiftUI中如何检测音量变化?需禁用OK按钮直至音量调至最大

解决方案

要实现检测音量变化并禁用未达最大音量时的OK按钮,你可以通过监听系统音量变化通知结合AVAudioSession获取当前音量来实现,具体步骤如下:

1. 补充导入必要框架

除已有的MediaPlayer,还需导入AVFoundation用于读取系统音量:

import AVFoundation

2. 修改VolumeAlertView实现监听与状态控制

添加状态变量跟踪音量是否达标,结合通知监听音量变化,动态控制按钮禁用状态:

struct VolumeAlertView: View {
    @Binding var isPresented: Bool
    @Binding var hasShown: Bool
    @State private var isVolumeMax = false // 标记音量是否达到最大
    private let volumeChangeNotification = NSNotification.Name(rawValue: "MPVolumeViewVolumeDidChangeNotification")
    
    var body: some View {
        ZStack {
            Rectangle()
                .foregroundStyle(Color(.systemGray6))
                .ignoresSafeArea()
            
            VStack(spacing: 24) {
                VStack(spacing: 20) {
                    Image(systemName: "speaker.wave.3.fill")
                        .font(.system(size: 50))
                        .foregroundStyle(.blue)
                    
                    Text("Volume")
                        .font(.title2.bold())
                    
                    Text("You must set your device volume to maximum.")
                        .multilineTextAlignment(.center)
                       
                }
                
                VolumeSliderView()
                    .frame(height: 40)
                    .padding()
                
                Button("OK") {
                    isPresented = false
                    hasShown = true
                }
                .buttonStyle(.borderedProminent)
                .controlSize(.extraLarge)
                .disabled(!isVolumeMax) // 根据音量状态禁用按钮
            }
            .padding()
            .background(Color(.systemGray6))
            .clipShape(RoundedRectangle(cornerRadius: 20))
            .padding(.horizontal)
        }
        .onAppear {
            checkCurrentVolume()
            // 注册音量变化通知
            NotificationCenter.default.addObserver(
                forName: volumeChangeNotification,
                object: nil,
                queue: .main
            ) { _ in
                checkCurrentVolume()
            }
        }
        .onDisappear {
            // 移除通知监听,避免内存泄漏
            NotificationCenter.default.removeObserver(
                self,
                name: volumeChangeNotification,
                object: nil
            )
        }
    }
    
    // 检查当前音量是否达标(考虑浮点精度,用0.99代替严格等于1.0)
    private func checkCurrentVolume() {
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setActive(true)
            let currentVolume = audioSession.outputVolume
            isVolumeMax = currentVolume >= 0.99
        } catch {
            print("获取音量失败:\(error.localizedDescription)")
        }
    }
}

// 原有VolumeSliderView代码保持不变
struct VolumeSliderView: UIViewRepresentable {
    func makeUIView(context: Context) -> MPVolumeView {
        let volumeView = MPVolumeView()
        volumeView.showsVolumeSlider = true
        volumeView.tintColor = .systemBlue
        return volumeView
    }
    
    func updateUIView(_ uiView: MPVolumeView, context: Context) {}
}

关键逻辑说明

  • 音量监听:通过MPVolumeViewVolumeDidChangeNotification监听系统音量变化,滑块调整或物理音量键操作都会触发该通知。
  • 音量判断:AVAudioSession.outputVolume返回0.0-1.0范围的音量值,用>=0.99替代严格等于1.0,避免浮点精度误差导致判断失效。
  • 按钮控制:直接通过disabled(!isVolumeMax)绑定按钮状态,只有音量达标时才可点击OK。

注意事项

  • 仅真机可见:MPVolumeView滑块在模拟器中无法显示,需使用物理设备测试。
  • 无需额外权限:iOS 10+系统读取音量无需申请权限,无需修改Info.plist。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 00:30:12