SwiftUIで、特定の数字から、0までカウントダウンする挙動を繰り返しおこない、繰り返した回数をセット数としてカウントする際に、どのように実装するかを悩んだのでここに書き留めておく。
1.読み上げ機能に関連するデリゲートの説明
2.読み上げ機能を行うクラスファイルを作成
3.クラスファイルにデリゲートを設定する。
1.読み上げ機能に関連するデリゲートの説明
読み上げた回数を数えるためには、AVSpeechSynthesizerDelegateを用いる必要があり、
デリゲートにより、
1読み上げが始まった
2読み上げが一時停止した
3読み上げが終わった
タイミングで処理を行う。
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クラスを作成する必要がある。
以下を作成した。
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.クラスファイルにデリゲートを設定する。
上記のクラスにデリゲートを設定する実装していく。
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