AVSpeechSynthesizer перестает работать примерно после 200 вызовов

Я использую AVSpeechSynthesizer для произнесения текста, после его использования для чего-то вроде 200 раз происходит какое-то странное поведение (в симуляторе macOS, а также в симуляторе iPad) после примерно 200 вызовов (synthesizer.speak(utterance)), все работает как положено , он внезапно попадает в метод didCancel() его AVSpeechSynthesizerDelegte и перестает работать навсегда! Даже didCancel больше никогда не вызывается, или любой из других методов делегата называется synthesizer.speak(utterance), просто заметьте.

Я попытался присвоить ссылку на синтезатор новому экземпляру AVSpeechSynthesizer внутри этого метода didCancel, но это не оказало на него никакого влияния, после того как метод didCancel накопился, единственное, что «заставит его вернуться», — это снова запустить приложение, а затем снова после использования метода синтезатора для примерно 200 вызовов он снова становится сломанным. это мой код:

   var synthesizer:AVSpeechSynthesizer! = AVSpeechSynthesizer()
       override func viewDidLoad() { 
synthesizer.delegate = self
}

    func speakText(utterance: AVSpeechUtterance ) {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, mode: .default, options: .mixWithOthers)
            try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
        } catch {
            print("audioSession properties weren't set because of an error.")
        }
        synthesizer.speak(utterance)
        
        print("speak now \(utterance.speechString)")
    }


  func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance) {
            
        print(" AVSpeechSynthesizerDelegate cancel")
      

        }

person yehudshe    schedule 21.09.2020    source источник
comment
Я столкнулся с той же проблемой.   -  person Guanghui Liao    schedule 14.06.2021


Ответы (1)


хорошо, мне удалось исправить эту проблему, я вызывал метод speakText(utterance: AVSpeechUtterance) из оператора if else, который менял текст высказывания по мере необходимости, а затем вызывал функцию внутри каждого блока (в блоках if и else)

что я сделал, так это получил высказывание за пределами блоков и присвоил ему значение nil: var utterance:AVSpeechUtterance. затем в блоках if else я присвоил ему соответствующее значение.

затем вне блоков я проверил, что значение было установлено, и если оно было установлено (не ноль). вся эта функциональность была искажена в функции, которая была запущена из синхронизированного блока глобального потока. вот так

DispatchQueue.global(qos: .userInteractive).sync{ [unowned self] in
            
            self.userDidEnterText(text: text)
            
        }

надеюсь, что такая ручка может дать идею или направление для кого-то, кто столкнется с этой проблемой в будущем.

person yehudshe    schedule 21.09.2020