トップ 最新 追記

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|06|07|08|09|10|11|

2024-10-10 [SwiftUI] TableView

ヒレガス本『Cocoa Programming for OS X (5th Edition)』のTableViewのサンプルをSwiftUIで実装してみた。

TableView

前回のSpeakLineはテキスト読み上げに利用する声をコードで求めていたが、今回のサンプルでは現在利用できる言語に対応した声から選択できるものとなる。

以下が、現在の言語で利用できる声のリストを返す関数。

func getVoices() -> [AVSpeechSynthesisVoice] {
    let locale = Locale(identifier:Locale.preferredLanguages[0])
    let voices = AVSpeechSynthesisVoice.speechVoices().filter { $0.language == locale.identifier }
    return voices
}

得られた声のリストでListを作成する。

struct ContentView: View {
    @State private var text = ""
    @ObservedObject private var speaker: Speaker = .init()
    private let voices = getVoices()
    @State var selectedVoice: AVSpeechSynthesisVoice?
    
    var body: some View {
        VStack {
            HStack {
                ZStack(alignment: .topLeading) {
                    TextEditor(text: $text)
                    
                    // prompt
                    if text.isEmpty {
                        Text("Enter text to be spoken...") .foregroundColor(Color.gray)
                            .padding(.horizontal, 6)
                    }
                }
                List(voices, id: \.self, selection: $selectedVoice) { voice in
                    Text(voice.name)
                }
            }
            HStack {
                Spacer()
                Button("Stop") {
                    print("stop button clicked")
                    speaker.stop()
                }.disabled(!speaker.isSpeaking)
                Button("Speak") {
                    if text.isEmpty {
                        print("string from TextEditor is empty")
                    } else {
                        print("string is \(text)")
                        if let voice = selectedVoice {
                            print("voice is \(voice)")
                            speaker.speak(text, voice: voice)
                        } else {
                            speaker.speak(text)
                        }
                    }
                }.disabled(speaker.isSpeaking)
            }
        }
        .padding()
    }
}

読み上げクラスも、声が渡された場合に対応。

final class Speaker: NSObject, AVSpeechSynthesizerDelegate, ObservableObject {
    func speak(_ text: String, voice: AVSpeechSynthesisVoice) {
        let utterance = AVSpeechUtterance(string: text)
        utterance.voice = voice
        speechSynth.speak(utterance)
    }
}

_ 【ソースコード】

GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/multiplatform/SpeakLine - GitHub

トップ 最新 追記