如何在外部类事件后更新SwiftUI按钮?



我要更新按钮,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 
}

最新更新