0
func listenVolumeButton(){
    do {
        try audioSession.setActive(true, options: [])
        audioSession.addObserver(self as! NSObject, forKeyPath: "outputVolume",
                                 options: NSKeyValueObservingOptions.new, context: nil)
        audioLevel = audioSession.outputVolume
        print("Value is \(audioLevel)")
    } catch {
        print("Error")
    }
}

override  func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "outputVolume" {
        let audioSession = AVAudioSession.sharedInstance()
        if audioSession.outputVolume > audioLevel {
            print("Hello up key pressed")
            
            if audioSession.outputVolume < audioLevel {
                print("Hello down key pressed")
                
                audioLevel = audioSession.outputVolume
                print(audioSession.outputVolume)
            }
        }
    }
}

当我们尝试删除观察者应用程序崩溃

audioSession.removeObserver(self, forKeyPath: "outputVolume")

它通过给出以下原因而崩溃

'无法从 <AVAudioSession 0x2817259d0> 中删除观察者或关键路径“outputVolume”,因为它没有注册为观察者。'

4

2 回答 2

0

我建议您使用块切换到现代 KVO 语法:

var outputVolumeObservation: NSKeyValueObservation?

func listenVolumeButton(){
    let audioSession = AVAudioSession.sharedInstance()
    do {
        try audioSession.setActive(true, options: [])
        outputVolumeObservation = audioSession.observe(\.outputVolume) { audioSession, _ in
            if audioSession.outputVolume > audioLevel {
                print("Hello up key pressed")

                if audioSession.outputVolume < audioLevel {
                    print("Hello down key pressed")

                    audioLevel = audioSession.outputVolume
                    print(audioSession.outputVolume)
                }
            }
        }
//      audioLevel = audioSession.outputVolume
//      print("Value is \(audioLevel)")
    } catch {
        print("Error")
    }
}

outputVolumeObservation它会在become时自动取消订阅nil,就像释放对象时一样:无需在deinit.

如果您需要手动停止收听,只需将其设置为nil

func stopListeningVolumeButton() {
    outputVolumeObservation = nil
}
于 2021-09-23T09:10:17.017 回答
0

再一次removeObserver,它触发,

像下面的代码:

func listenVolumeButton(){
        do {
            try audioSession.setActive(true, options: [])
            audioSession.addObserver(self as! NSObject, forKeyPath: "outputVolume",
                                     options: NSKeyValueObservingOptions.new, context: nil)
            audioLevel = audioSession.outputVolume
            print("Value is \(audioLevel)")
        } catch {
            print("Error")
        }
        
        audioSession.removeObserver(self, forKeyPath: "outputVolume")
        audioSession.removeObserver(self, forKeyPath: "outputVolume")
        
    }

它崩溃了,Xcode 报告:

 *** Terminating app due to uncaught exception 'NSRangeException', 

reason: 'Cannot remove an observer <aaaa.ViewController 0x106a06e90> for the key path "outputVolume" from <AVAudioSession 0x281020370> 

because it is not registered as an observer.'


至于你,removeObserver不应该叫 in viewwillDisappear,而是 indeinit{}

例如,您的控制器是B

  • ctrl A -> ctrl B -> ctrl C

  • ctrl A <- ctrl B <- ctrl C

  • ctrl B -> ctrl CremoveObserver一次,

  • ctrl A <- ctrl BremoveObserver再次崩溃

于 2021-09-27T06:28:51.953 回答