我要更新按钮,from "pause"签名,回到"玩"。标志;下课后做演讲任务。当前代码没有做任何更改…怎么了?
我可以做有条件的.onChange
吗?(仅当更改是特定的)
struct SwiftUIView: View {
var speaker = Speaker()
@State var isPlaying = false
var body: some View {
VStack {
Button(action: {
if isPlaying {
isPlaying.toggle()
speaker.synth.pauseSpeaking(at: .immediate)
} else {
isPlaying.toggle()
// continue playing here if it was paused before, else ignite speech utterance
if speaker.synth.isPaused {
speaker.synth.continueSpeaking()
} else {
speaker.speak("Holly Molly bro")
}
}
}, label: {
Text(isPlaying ? "pause" : "play")
})
}
.onChange(of: speaker.hasStopped, perform: { value in
isPlaying = false
print("Who asked for change?")
})
}
}
…
import AVFoundation
import Combine
class Speaker: ObservableObject, AVSpeechSynthesizerDelegate {
let synth = AVSpeechSynthesizer()
@Published var hasStopped: Bool = false
func speak(_ string: String) {
hasStopped = false
let utterance = AVSpeechUtterance(string: string)
utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
utterance.rate = 0.4
synth.speak(utterance)
}
func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
print("all done")
hasStopped = true
}
}
您需要将ObservableObject
属性包装到ObservedObject
包装器中,以便跟踪发布的属性,如
struct SwiftUIView: View {
@ObservedObject var speaker = Speaker() // << here !!
// @StateObject var speaker = Speaker() // << if single per view !!
除了Asperi的回答,你还需要设置Delegate:
override init() {
super.init()
synth.delegate = self
}