AVAudioSequencer Causes Crash on Deinit/Segue: 'required condition is false: outputNode'

非 Y 不嫁゛ 提交于 2019-12-20 06:36:31

问题


The below code causes a crash with the following errors whenever the object is deinitialized (e.g. when performing an unwind segue back to another ViewController):

required condition is false: [AVAudioEngineGraph.mm:4474:GetDefaultMusicDevice: (outputNode)]

Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'required condition is false: outputNode'

The AVAudioSequencer is the root of the issue, because the error ceases if this is removed.

How can this crash be avoided?

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:


This crash can be confusing, and may also output no error message whatsoever to the console if the sequencer's content hasn't been loaded yet. Very unhelpful!

The AVAudioSequencer is indeed the cause of the issue. To fix it, make the sequencer an implicitly unwrapped optional (i.e. add ! to its type) and add explicit instructions to stop & remove it during deinit, before the rest of the object is deinitialized.

The fixed code is as follows (take note of the deinit method especially):

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
    }
}

Hope this helps!



来源:https://stackoverflow.com/questions/58036260/avaudiosequencer-causes-crash-on-deinit-segue-required-condition-is-false-out

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!