1

I have a collection view with paging enabled. I am using AVSpeechSynthesizer for text to speech in the cells of the collection view. I want the voice to stop when i swipe from one cell to another. Right now i am calling stopSpeech function, which is declared in the cell class.

//Cell Class
import UIKit
import AVFoundation

class DetailArticleCell: UICollectionViewCell, AVSpeechSynthesizerDelegate {
    @IBOutlet weak var articleImage: UIImageView!
    @IBOutlet weak var articleText: UILabel!
    @IBOutlet weak var textToSpeechBGView: UIVisualEffectView!
    @IBOutlet weak var textToSpeechButton: UIButton!
    var isSpeaking: Bool = true
    let speechSynthesizer = AVSpeechSynthesizer()
    var speechText: String!

    override func awakeFromNib() {
        textToSpeechBGView.layer.cornerRadius = 0.5 * textToSpeechBGView.bounds.size.width
        textToSpeechBGView.clipsToBounds = true
        setImageForTextSpeech()
        speechSynthesizer.delegate = self

    }

    func setImageForTextSpeech(){
        isSpeaking ? textToSpeechButton.setImage(#imageLiteral(resourceName: "noAudio"), for: .normal) : textToSpeechButton.setImage(#imageLiteral(resourceName: "audio"), for: .normal)
    }

    func receive(text: String) -> String{
        return text
    }
    func speak(text: String){
        let speechUtterance = AVSpeechUtterance(string: text)
       // speechUtterance.rate = 1.0
        speechSynthesizer.speak(speechUtterance)
        isSpeaking = false
    }
    func stopSpeech(){
      speechSynthesizer.stopSpeaking(at: .immediate)
      isSpeaking = true
    }

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        isSpeaking = true
        setImageForTextSpeech()
    }


    @IBAction func textToSpeechAction(_ sender: Any) {
        print("clicked")

        if isSpeaking {
            guard let textContent = speechText else {
                speak(text: "")
                return
            }
            speak(text: textContent)

        } else {
            stopSpeech()
        }
        setImageForTextSpeech()
    }


}

I am then calling the function in the didEndDisplayingCell method of the collectionView.

func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {

    let cell=collectionView.dequeueReusableCell(withReuseIdentifier: "detailArticleCell", for: indexPath) as! DetailArticleCell  
    cell.stopSpeech()
}

This works only on every third cell. But i want the voice to stop when the user swipes to the next cell every time.

Ashiq Sulaiman
  • 631
  • 1
  • 6
  • 14

1 Answers1

0

Change this line:

let cell=collectionView.dequeueReusableCell(withReuseIdentifier: "detailArticleCell", for: indexPath) as! DetailArticleCell  

to:

if let detailCell = cell as? DetailArticleCell
{
     detailCell.stopSpeech()
}

and see what happens.

That delegate method already provides a parameter with the cell that's not being displayed anymore, so there's no need to call dequeueReusableCell (which might be giving you something unexpected).

Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215