AVAudioSequencer вызывает сбой при Deinit / Segue: «обязательное условие ложно: outputNode» - PullRequest
0 голосов
/ 21 сентября 2019

Приведенный ниже код вызывает сбой со следующими ошибками при каждой деинициализации объекта (например, при выполнении отката назад к другому ViewController):

обязательное условие ложно: [AVAudioEngineGraph.mm:4474: GetDefaultMusicDevice: (outputNode)] *

Завершение работы приложения из-за необработанного исключения 'com.apple.coreaudio.avfaudio', причина: 'обязательное условие: false: 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 голосов
/ 21 сентября 2019

Этот сбой может сбить с толку и может также не выводить сообщение об ошибке на консоль, если содержимое секвенсора еще не было загружено.Очень бесполезно!

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

Надеюсь, это поможет!

...