今回の記事では、音声出力などの時間的に長い処理の制御の仕方についてご紹介します。
基本的に音声を出力する際の次の処理に関しては何かしらの処理方法を考えなければ、非同期処理により、どんどん処理は進んでいってしまいます。
同期処理に関しての記述はたくさんありますが同期処理と非同期処理書くとやっぱり複雑なソースコードになってしますので今回は同期・非同期処理を用いずにタイトルのように順番に処理を行う方法を紹介します。
音声出力処理を「音声出力」→「音声読み上げ完了」→「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」の順番に処理を行なっています。
コメント