SwiftUI detect system volume change

I'm trying to update my SwiftUI view when system volume changes. Ultimately, my use case is to display a low volume warning overlay when the system volume is low. Right now, though, let's say I'm just trying to show the current volume in a Text label. I've tried using onReceive with a publisher on AVAudioSession.sharedInstance().outputVolume, as in below, but my onReceive block only fires once when the view appears, and is not called when the volume subsequently changes. Why does the below not work, and what is the best way to update SwiftUI views when volume changes?

struct Test: View {
    @State var volume: Float = 0

    var body: some View {
        Text("current volume is \(volume)")
        .onReceive(AVAudioSession.sharedInstance().publisher(for: \.outputVolume), perform: { value in
            self.volume = value
        })
    }
}

Thanks!

Post not yet marked as solved Up vote post of thenewpotato Down vote post of thenewpotato
2.4k views

Replies

you need to activate the audio session before it sends updates on Volume changes to your app.

AVAudioSession.sharedInstance().setActive(true)