2

What I am trying to do is press the speak button which will highlight the first paragraph and then speak that paragraph, then scroll the next paragraph to center of the textView and highlight that one and speak it and so own. What code would I have to add to do this?

import UIKit
import AVFoundation


class TestViewController: UIViewController, AVSpeechSynthesizerDelegate {

let synthesizer = AVSpeechSynthesizer()


@IBOutlet weak var textViewOutlet: UITextView!


@IBAction func pauseSpeech(_ sender: Any) {
    synthesizer.pauseSpeaking(at: AVSpeechBoundary.word)
}

@IBAction func stopSpeech(_ sender: Any) {
    synthesizer.stopSpeaking(at: .word)
}

@IBAction func cancelButton(_ sender: Any) {
    synthesizer.continueSpeaking()
}

@IBAction func speak(_ sender: AnyObject) {
    let string = textViewOutlet.text!
    let utterance = AVSpeechUtterance(string: string)
        utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
        synthesizer.speak(utterance)
}


override func viewDidLoad() {
    super.viewDidLoad()
        synthesizer.delegate = self
        textViewOutlet.font = .systemFont(ofSize: 20)
}

func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) {
    let mutableAttributedString = NSMutableAttributedString(string: utterance.speechString)
        mutableAttributedString.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.blue, range:  NSMakeRange(0, (utterance.speechString as NSString).length))
        mutableAttributedString.addAttribute(.foregroundColor, value: UIColor.red, range: characterRange)
        textViewOutlet.attributedText = mutableAttributedString
        textViewOutlet.font = .systemFont(ofSize: 20)
}

func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
    textViewOutlet.attributedText = NSAttributedString(string: utterance.speechString)
    textViewOutlet.font = .systemFont(ofSize: 20)
}

}
dscrown
  • 578
  • 1
  • 5
  • 21

1 Answers1

-1

Something like this:

Define properties

   let currentParagraphIndex = 0
   let paragraphs = [Range<String.Index>]()

On start

   let text = textViewOutlet.text!
   paragraphs = splitOnParagraphs(text)
   currentParagraphIndex = 0
   highlightParagraph(paragraphs[currentParagraphIndex])
   let utterance = AVSpeechUtterance(text.substringWithRange(paragraphs[currentParagraphIndex]))
   utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
   synthesizer.speak(utterance)

See also Split paragraphs into Sentences

So you start speaking the first paragraph, not just text.

Then, when paragraph is ended, in delegate you start speaking next paragraph:

func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
    currentParagraphIndex = currentParagraphIndex + 1
    if (currentParagraphIndex < paragraphs.count) {
       let utterance = AVSpeechUtterance(text.substringWithRange(paragraphs[currentParagraphIndex]))
       highlightParagraph(currentParagraphIndex)
       utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
       synthesizer.speak(utterance)
     }
}
Nikolay Shmyrev
  • 24,897
  • 5
  • 43
  • 87
  • I can't figure out how to work it out with this answer so I edited my question. Thanks for the direction I have learnt more about it. – dscrown Mar 30 '18 at 12:54