AVAudioSequencer导致Deinit / Segue崩溃:“所需条件为假:outputNode”

时间:2019-09-21 00:04:24

标签: ios swift avfoundation core-audio avaudioengine

下面的代码在对象被取消初始化时(例如,在执行退回搜索到另一个ViewController时)会导致以下错误:

  

所需条件为假:[AVAudioEngineGraph.mm:4474:GetDefaultMusicDevice:(outputNode)]

     

由于未捕获的异常“ com.apple.coreaudio.avfaudio”而终止应用程序,原因:“所需条件为假:outputNode”

AVAudioSequencer是问题的根源,因为如果删除该错误,错误就会停止。

如何避免这种崩溃?

class TestAudioClass {

    private var audioEngine: AVAudioEngine
    private var sampler: AVAudioUnitSampler
    private var sequencer: AVAudioSequencer

    init() {
        self.audioEngine = AVAudioEngine()
        self.sampler = AVAudioUnitSampler()
        audioEngine.attach(sampler)
        audioEngine.connect(sampler, to: audioEngine.mainMixerNode, format: nil)
        self.sequencer = AVAudioSequencer(audioEngine: audioEngine)
        if let fileURL = Bundle.main.url(forResource: "TestMusic", withExtension: "mid") {
            do {
                try sequencer.load(from: fileURL, options: AVMusicSequenceLoadOptions())
            } catch {
                print("Error loading sequencer: \(error.localizedDescription)")
            }
        }
        sequencer.prepareToPlay()
    }
}

1 个答案:

答案 0 :(得分:0)

此崩溃可能会造成混乱,并且如果尚未加载音序器的内容,也可能不会向控制台输出任何错误消息。非常无益!

AVAudioSequencer确实是问题的原因。要解决此问题,请使音序器成为隐式解包的可选内容(即在其类型中添加!),并添加明确的指令以在deinit期间停止并删除它,在其余时间 该对象已取消初始化。

固定代码如下(特别注意deinit方法):

class TestAudioClass {

    private var audioEngine: AVAudioEngine
    private var sampler: AVAudioUnitSampler
    private var sequencer: AVAudioSequencer!

    init() {
        self.audioEngine = AVAudioEngine()
        self.sampler = AVAudioUnitSampler()
        audioEngine.attach(sampler)
        audioEngine.connect(sampler, to: audioEngine.mainMixerNode, format: nil)
        self.sequencer = AVAudioSequencer(audioEngine: audioEngine)
        if let fileURL = Bundle.main.url(forResource: "TestMusic", withExtension: "mid") {
            do {
                try sequencer.load(from: fileURL, options: AVMusicSequenceLoadOptions())
            } catch {
                print("Error loading sequencer: \(error.localizedDescription)")
            }
        }
        sequencer.prepareToPlay()
    }

    deinit {
        sequencer.stop()
        sequencer = nil
    }
}

希望这会有所帮助!