A does not conform to protocol NSObjectProtocol
means that your class must inherit from NSObject, you can read more about it here.
Now I don't know how you've structured your code, but this little example seems to work for me. First a dead simple class that holds the AVSpeechSynthesizer
:
class Speaker: NSObject {
let synth = AVSpeechSynthesizer()
override init() {
super.init()
synth.delegate = self
}
func speak(_ string: String) {
let utterance = AVSpeechUtterance(string: string)
synth.speakUtterance(utterance)
}
}
Notice that I set the delegate here (in the init
method) and notice that it must inherit from NSObject
to keep the compiler happy (very important!)
And then the actual delegate method:
extension Speaker: AVSpeechSynthesizerDelegate {
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
print("all done")
}
}
And finally, I can use that class here, like so:
class ViewController: UIViewController {
let speaker = Speaker()
@IBAction func buttonTapped(sender: UIButton) {
speaker.speak("Hello world")
}
}
Which rewards me with
all done
in my console when the AVSpeechSynthesizer
has stopped speaking.
Hope that helps you.
Update
So, time passes and in the comments below @case-silva asked if there was a practical example and @dima-gershman suggested to just use the AVSpeectSynthesizer
directly in the ViewController
.
To accommodate both, I've made a simple ViewController
example here with a UITextField
and a UIButton
.
The flow is:
- You enter some text in the textfield (if not, a default value will be set)
- You press the button
- The button is disabled and the background color is changed (sorry, it was the best I could come up with :))
- Once speech is done, the button is enabled, the textfield is cleared and the background color is changed again.
Here's how it looks
A Simple UIViewController
Example
import UIKit
import AVFoundation
class ViewController: UIViewController {
//MARK: Outlets
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var speakButton: UIButton!
let synth = AVSpeechSynthesizer()
override func viewDidLoad() {
super.viewDidLoad()
synth.delegate = self
}
@IBAction func speakButtonTapped(_ sender: UIButton) {
//We're ready to start speaking, disable UI while we're speaking
view.backgroundColor = .darkGray
speakButton.isEnabled = false
let inputText = textField.text ?? ""
let textToSpeak = inputText.isEmpty ? "Please enter some text" : inputText
let speakUtterance = AVSpeechUtterance(string: textToSpeak)
synth.speak(speakUtterance)
}
}
extension ViewController: AVSpeechSynthesizerDelegate {
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
//Speaking is done, enable speech UI for next round
speakButton.isEnabled = true
view.backgroundColor = .lightGray
textField.text = ""
}
}
Hope that gives you a clue Case.