简体   繁体   中英

Why does the second call to my function get triggered twice? (Swift iOS timer/speechrecognition)

self.adaResponseApi runs twice when the timer hits 1.5 seconds after the last recorded speech input. It should only run once.

It is specifically running from the 1.5 interval instantiation and not from the first instantiation, which is triggered when the user specifically-stops speech input.

recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest, resultHandler: { (result, error) in
    if result != nil {
        self.textView.text = result?.bestTranscription.formattedString
        self.isFinal = (result?.isFinal)!
    }

    if let timer = self.detectionTimer, (timer.isValid) {
        if self.isFinal! {
            self.detectionTimer?.invalidate()
            self.adaResponseApi()
            self.isFinal = true
        }
    } else  { // if self.isFinal == false
        self.detectionTimer = Timer.scheduledTimer(withTimeInterval: 1.5, repeats: false, block: { timer in
            self.adaResponseApi() // This call gets triggered twice and for the life of me I can't figure out why.
            timer.invalidate()
            self.isFinal = true
        })
    }
})

OK here goes... I'm assuming that the request has shouldReportPartialResults set to true (default value).

recognitionTask = speechRecognizer.recognitionTask(with: recognitionRequest) { [weak self] (result, error) in
    // [weak self] to stop memory leaks

    guard let result = result else {
        // no result means probably an error, you should report that to your user
        return
    }

    // display the most accurate transcription (partial or final)
    self?.textView.text = result.bestTranscription.formattedString

    // invalidate timer
    // result is final (and so should invalidate timer)
    // or result is partial (and so will create new timer ... and invalidate this one)
    self?.detectionTimer?.invalidate()

    if result.isFinal {
        // we have a final result... use it
        self?.adaResponseApi()
    } else {
        // create timer for if the next response times out
        self?.detectionTimer = Timer.scheduledTimer(withTimeInterval: 1.5, repeats: false) { [weak self] timer in
            self?.adaResponseApi()
        }
    }
}

I think I would do it something like this...

I'm not 100% certain what your timer is there for so I assumed it's there in case the recogniser does not return a response quickly and so we can fall back to the most recent partial result?

I also don't think we should need to store the value of result.isFinal . If you do need that then you can add it to the line after self?.textView.text = result.bestTranscription.formattedString .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM