スポンサーリンク

【Swift】「音声読み上げ後」→「labelの色変更」のように処理を制御するDelegateの設定方法。

Swift
スポンサーリンク

今回の記事では、音声出力などの時間的に長い処理の制御の仕方についてご紹介します。
基本的に音声を出力する際の次の処理に関しては何かしらの処理方法を考えなければ、非同期処理により、どんどん処理は進んでいってしまいます。

同期処理に関しての記述はたくさんありますが同期処理と非同期処理書くとやっぱり複雑なソースコードになってしますので今回は同期・非同期処理を用いずにタイトルのように順番に処理を行う方法を紹介します。

スポンサーリンク

音声出力処理を「音声出力」→「音声読み上げ完了」→「labelの色変更」のように制御するXcode設定

Xcodeの設定は特に変わったところはありません。
通常のアプリ作成画面からボタンなどのガジェットをStoryboardに接続してください。

下記のようにすれば初めはOKです。

Swiftで音声を出力する方法

音声出力のライブラリ「speechSynthesizer」を使用します。
まずこの関数のクラスである「AVFoundation」をimportします。

音声出力のみの場合は下記コードで実行できます。

let utterance = AVSpeechUtterance(string: "テスト")
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
self.talker.speak(utterance)

まずは出力する日本語を文字列として定義。
その下で言語を日本語に指定。
最後のspeakで音声を出力しています。

次に「delegate」を使用するため「AVSpeechSynthesizerDelegate」クラスを追加します。

この「speechSynthesizer」のインスタンスを取得して制御を行っていくとおいう流れがdelegateを用いた処理順番の制御です。

あとは「delegate」を「viewdidload」で呼び込んでくるだけです。

上記の実装用のコードは下記です。

import UIKit
import AVFoundation

class ViewController: UIViewController {
    @IBOutlet weak var syori1: UILabel!
    @IBOutlet weak var syori2: UILabel!
    //インスタンス作成
    var talker = AVSpeechSynthesizer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        syori1.backgroundColor = UIColor.blue
        syori2.backgroundColor = UIColor.red
        // Do any additional setup after loading the view.
    }
    override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
    }
    //音声出力ボタン
    @IBAction func test_onsei(_ sender: Any) {
        let utterance = AVSpeechUtterance(string: "テストながめのぶんしょうをながしております。テストしゅうりょうです。")
        utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
        self.talker.speak(utterance)
    }
}

このテストで出力した長めの文章を出力する前と後でLabelの色を変えていくコードを以下で2通りの方法を使って説明していきます。

音声出力処理を「音声出力」→「音声読み上げ完了」→「labelの色変更」のように制御するSwiftコード

上記のコードに以下に追記したものを先に載せます。

import UIKit
import AVFoundation

class ViewController: UIViewController,AVSpeechSynthesizerDelegate {

    @IBOutlet weak var syori1: UILabel!
    @IBOutlet weak var syori2: UILabel!
    //インスタンス作成
    var talker = AVSpeechSynthesizer()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        syori1.backgroundColor = UIColor.blue
        syori2.backgroundColor = UIColor.red
        //delegateの読み込み
        self.talker.delegate = self
        // Do any additional setup after loading the view.
    }
    override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
    }
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {
        print("start")
        syori1.backgroundColor = UIColor.gray
    }
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        print("finish")
        syori2.backgroundColor = UIColor.gray
    }

    @IBAction func test_onsei(_ sender: Any) {
        let utterance = AVSpeechUtterance(string: "テストながめのぶんしょうをながしております。テストしゅうりょうです。")
        utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
        self.talker.speak(utterance)
    }
}

追加している箇所の解説です。

まずはクラスを追加しております。一番上あたりのviewcontrollerの横です。
これでdelegateを使用できるように下記viewdidloadにも下記を追記して読み込ませております。

//delegateの読み込み
self.talker.delegate = self

次に下記関数で話し始めと終わりを取得しております。

func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {
        print("start")
        syori1.backgroundColor = UIColor.gray
}
    
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
        print("finish")
        syori2.backgroundColor = UIColor.gray
}

関数の引数に「didstart」「didfinish」と書いてあるので分かりやすいですが上記の関数内の処理を音声出力はじめと終わりに処理してくれます。

下記のように左から画面遷移するはずです。

複数のLabelを音声出力の読み上げ後に出力完了させたい場合は音声終了検知関数の中に二つのLabelの色変更を行なっておけばOKです。

同期処理を使用した処理順番の制御

同期処理を使う前にまずは同期処理を使わないで順番に処理を書いてみましょう。

import UIKit
import AVFoundation

class ViewController: UIViewController {

    @IBOutlet weak var syori1: UILabel!
    @IBOutlet weak var syori2: UILabel!

    var talker = AVSpeechSynthesizer()
    //インスタンス作成
    override func viewDidLoad() {
        super.viewDidLoad()
        syori1.backgroundColor = UIColor.blue
        syori2.backgroundColor = UIColor.red
        // Do any additional setup after loading the view.
    }
    override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
    }
    @IBAction func test_onsei(_ sender: Any) {
        //1つ目の音声出力
        let utterance1 = AVSpeechUtterance(string: "テストながめのぶんしょうをながしております。テストしゅうりょうです。1")
        utterance1.voice = AVSpeechSynthesisVoice(language: "ja-JP")
        self.talker.speak(utterance1)
        
        //1つ目のラベルの色を変える処理
        syori1.backgroundColor = UIColor.gray
        
        //2つ目の音声出力
        let utterance2 = AVSpeechUtterance(string: "テストながめのぶんしょうをながしております。テストしゅうりょうです。2")
        utterance2.voice = AVSpeechSynthesisVoice(language: "ja-JP")
        self.talker.speak(utterance2)
        
        //2つ目のラベルの色を変える処理
        syori2.backgroundColor = UIColor.gray
    }
}

下記で実行すると先にLabelの色が全て変わった後に音声出力が始まります。
これは音声出力の処理がLabelの色変換よりも時間がかかるので非同期処理では仕方ありません。

これを順番に処理させられるように書き換えることで「音声出力1」→「ラベルの色変換1」→「音声出力2」→「ラベルの色変換2」の順番に処理を行なっています。

本記事を読んでいただき感謝です。サイトを訪れていただいた方はプログラミング勉強中かと思いますのでプログラミング勉強のコツを合わせてご紹介。

スポンサーリンク
スポンサーリンク
スポンサーリンク

ブログに関しては500円程度かかりますが、それ以外は無料です。知識の吸収と並行してアウトプットは非常に効率が良いです。テックアカデミーに関しては講座レベルが高いにも関わらず、無料体験や人気口座も大幅値下げがあるので、重点的に学びたいものを無料体験してみてください。

転職時にも、エンジニアからテックアカデミー・Paizaは認知度が高いので、未経験入社採用を行う際履歴書で目に留まります。特にPaizaのスキルレベルA・SなどはIT業界でも評価されます。

テックアカデミー・Paizaの無料登録ができる期間中にぜひご利用してみてください。私も活用経験ありです。

Swift
スポンサーリンク
スポンサーリンク

コメント

タイトルとURLをコピーしました