在 SwiftUI 中观察系统音量

Observing system volume in SwiftUI

我想在我的应用程序中显示音量指示器,但首先我需要监控系统当前音量。

我正在使用观察器,虽然打印语句显示正确的值,但 UI 从来没有。

import SwiftUI
import MediaPlayer

struct ContentView: View {
    @State var vol: Float = 1.0

    // Audio session object
    private let session = AVAudioSession.sharedInstance()
    // Observer
    private var progressObserver: NSKeyValueObservation!

    init() {
            do {
                try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.ambient)
                try session.setActive(true, options: .notifyOthersOnDeactivation)
                self.vol = 1.0
            } catch {
                print("cannot activate session")
            }

            progressObserver = session.observe(\.outputVolume) { [self] (session, value) in
                print(session.outputVolume)
                self.vol = session.outputVolume
            }
        }

    var body: some View {
        Text(String(self.vol))
    }
}

// 固定(将类别设置为环境)(更新以上代码) 此外,每次启动该应用程序时,它都会停止所有当前正在播放的音乐。

已解决。创建了一个符合 ObservableObject 的 class 并在视图中使用 ObservedObject 属性。此外,卷观察器在模拟器中不起作用,仅在设备上起作用。

VolumeObserver.swift

import Foundation
import MediaPlayer

final class VolumeObserver: ObservableObject {

    @Published var volume: Float = AVAudioSession.sharedInstance().outputVolume

    // Audio session object
    private let session = AVAudioSession.sharedInstance()

    // Observer
    private var progressObserver: NSKeyValueObservation!

    func subscribe() {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.ambient)
            try session.setActive(true, options: .notifyOthersOnDeactivation)
        } catch {
            print("cannot activate session")
        }

        progressObserver = session.observe(\.outputVolume) { [self] (session, value) in
            DispatchQueue.main.async {
                self.volume = session.outputVolume
            }
        }
    }

    func unsubscribe() {
        self.progressObserver.invalidate()
    }

    init() {
        subscribe()
    }
}

ContentView.swift

import SwiftUI
import MediaPlayer

struct ContentView: View {

    @ObservedObject private var volObserver = VolumeObserver()

    init() {
        print(vol.volume)
    }

    var body: some View {
        Text(String(vol.volume))
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}