Whenever I navigate to this view controller, the speakText()
function in viewDidLoad
for some reason doesn't work and the view controller takes a long time to load (this is not the case when I remove that line). Above that line, a text label's text is set to the string that is meant to be spoken, and works fine. Each time recordTapped
is called, the speech synthesis works perfectly. However, it just doesn't seem to work in viewDidLoad
.
UPDATE I have done some more testing, after assigning the view controller delegate of the speech synthesiser and running the function asynchronously. However, it doesn't work. I set the view controller to initial view controller and it still doesn't work, so it isn't a problem in navigation and load time is still very long.
import UIKit
import AVFoundation
class StartViewController: UIViewController, AVAudioRecorderDelegate {
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var recordButton: UIButton!
let synth = AVSpeechSynthesizer()
var myUtterance = AVSpeechUtterance(string: "")
var number = 0
override func viewDidLoad() {
super.viewDidLoad()
synth.delegate? = self as! AVSpeechSynthesizerDelegate
number = 0
DispatchQueue.global(qos: .userInitiated).async {self.speakText(int: number)}
self.number = self.number + 1
}
@IBAction func recordTapped(_ sender: UIButton) {
speakText(int: number)
number = number + 1
}
func speakText(int: Int) {
myUtterance = AVSpeechUtterance(string: "the number is \(int)")
myUtterance.voice = AVSpeechSynthesisVoice(language: "en-AU")
synth.speak(myUtterance)
}
}
As I said in the comments, multithreading works. Just tested myself. Working code below, please test and confirm. It is always good to rely on separate thread for speech.
Plus, To call Speech whenever view appears, call it from
viewWillAppear()
orviewDidAppear()
and not fromviewDidLoad()
, since the latter is called once when the app is in foreground.