我有点卡住了。

这是我的代码:

let speaker = AVSpeechSynthesizer()
var playQueue = [AVSpeechUtterance]() // current queue
var backedQueue = [AVSpeechUtterance]() // queue backup

...

func moveBackward(_ currentUtterance:AVSpeechUtterance) {
    speaker.stopSpeaking(at: .immediate)
    let currentIndex = getCurrentIndexOfText(currentUtterance)
    // out of range check was deleted
    let previousElement = backedQueue[currentIndex-1]
    playQueue.insert(previousElement, at: 0)
    for utterance in playQueue {
        speaker.speak(utterance) // error here
    }
}

根据文档AVSpeechSynthesizer.stopSpeaking(at:):

停止合成器将取消任何进一步的语音;与…相反
合成器暂停时,语音无法从其离开的地方恢复
关。 所有尚未说出的话语都将从
合成器的队列


当我在AVSpeechSynthesizer队列中插入AVSpeechUtterance时,总是会收到错误消息(AVSpeechUtterance不会入队两次)。但是应该根据文档停止。

最佳答案

当停止播放器时,话语肯定会从队列中删除。

但是,在moveBackward函数中,您在AVSpeechUterrance处插入另一个playQueue[0],其完整数组代表播放器队列。

假设停止是通过currentIndex = 2进行的,以下快照证明了将同一对象两次注入队列中:

  • 复制backedQueue[1],它是playQueue[1]的副本(相同的内存地址)。
    ios - AVSpeechSynthesizer错误:AVSpeechUtterance不应入队两次-LMLPHP
  • backedQueue[1]处插入playQueue[0](以前的playQueue[1]变为新的playQueue[2])。
    ios - AVSpeechSynthesizer错误:AVSpeechUtterance不应入队两次-LMLPHP

  • 不幸的是,正如系统指示的那样,AVSpeechUtterance不应两次入队,这正是您在这里所做的:playQueue索引0和2 上的对象具有相同的内存地址

    在索引为0处插入新对象之后的最后一个循环要求语音合成器将所有语音放入其所有新队列中,并且其中两个是相同的。

    建议不要将playedQueue复制到backedQueue(两个对象都包含相同的内存地址)或在两个数组中添加相同的发音,而建议创建不同的发音实例,如下所示:
        for i in 1...5 {
    
            let stringNb = "number " + String(i) + " of the speech synthesizer."
            let utterance = AVSpeechUtterance(string: stringNb)
            playQueue.append(utterance)
    
            let utteranceBis = AVSpeechUtterance(string: stringNb)
            backedQueue.append(utteranceBis)
        }
    

    按照这一建议,您不应遇到错误AVSpeechUtterance不会被排队两次的情况。

    关于ios - AVSpeechSynthesizer错误:AVSpeechUtterance不应入队两次,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53606746/

    10-12 14:35