1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【iOS】読み上げ機能を用いて、読み上げた回数をカウントする実装

Last updated at Posted at 2023-04-09

SwiftUIで、特定の数字から、0までカウントダウンする挙動を繰り返しおこない、繰り返した回数をセット数としてカウントする際に、どのように実装するかを悩んだのでここに書き留めておく。

1.読み上げ機能に関連するデリゲートの説明
2.読み上げ機能を行うクラスファイルを作成
3.クラスファイルにデリゲートを設定する。

1.読み上げ機能に関連するデリゲートの説明

読み上げた回数を数えるためには、AVSpeechSynthesizerDelegateを用いる必要があり、
デリゲートにより、
1読み上げが始まった
2読み上げが一時停止した
3読み上げが終わった
タイミングで処理を行う。

Speaker.swift

extension Speaker: AVSpeechSynthesizerDelegate {

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {
            // 1読み上げが始まったときに処理される
    }

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didPause utterance: AVSpeechUtterance) {
            // 2読み上げが一時停止したときに処理される
    }

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
            // 3読み上げが終わったときに処理される
    }

    // etc...

}

2.読み上げ機能を行うクラスファイルを作成

このデリゲートに準拠するクラスが必要であり、そのためにSpeakerクラスを作成する必要がある。
以下を作成した。

Speaker.swift
final class Speaker: NSObject, ObservableObject {

   // 止まっているか、一時停止しているか、読み上げているかを管理するプロパティ
    @Published var state: State = .inactive
    enum State: String {
        case inactive, speaking, paused
    }

   // 読み上げた回数を管理するプロパティ
    @Published var countSpeech: Int = 0

    // 以降は読み上げ機能を実装している。
    private let synth: AVSpeechSynthesizer = .init()
    override init() {
        super.init()
        synth.delegate = self
    }
    func speak(word: String,language: String,rate: Float, pitch: Float) {
        let utterance = AVSpeechUtterance(string: word)
        utterance.voice = AVSpeechSynthesisVoice(language: language)

        utterance.rate = rate
        utterance.pitchMultiplier = pitch
        synth.speak(utterance)
    }
    func stop() {
        synth.stopSpeaking(at: .immediate)
    }
}

3.クラスファイルにデリゲートを設定する。

上記のクラスにデリゲートを設定する実装していく。

Speaker.swift
extension Speaker: AVSpeechSynthesizerDelegate {

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {
        // 読み上げが始まった際に実行され、状態を管理するプロパティに代入
        state = .speaking
    }

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didPause utterance: AVSpeechUtterance) {
        // 読み上げが一時停止した際に実行され、状態を管理するプロパティに代入
        state = .paused
    }

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        // 読み上げが終了時点で処理が実行されるため、この関数内に読み上げ回数を管理している
        // プロパティに+1を行う。
        countSpeech += 1
        // 読み上げが終了した際に実行され、状態を管理するプロパティに代入
        state = .inactive
    }

    // etc...

}

以上で、読み上げた回数を管理することが可能になりました。

UIkitは、ViewContollerにデリゲートを設定していたが、SwiftUIはContentViewにデリゲートを設定できず、モデル部分にデリゲートを設定して、管理していく必要があるんですね。

他にも良い方法があれば、コメントいただけると大変うれしいです。
良かったと思ったら、いいねやTwitterのフォローよろしくお願いいたします!

https://sites.google.com/view/muranakar
個人でアプリを作成しているので、良かったら覗いてみてください!

以下を参考にしました。
https://stackoverflow.com/questions/61248666/avspeechsynthesizerdelegate-implementation-in-swiftui

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?