如何在外部类中的事件后更新 SwiftUI 按钮?
Posted
技术标签:
【中文标题】如何在外部类中的事件后更新 SwiftUI 按钮?【英文标题】:How to update SwiftUI button after event in external class? 【发布时间】:2021-02-13 10:19:51 【问题描述】:我想更新按钮,从“暂停”标志,回到“播放”标志;当班级完成演讲任务时。当前代码没有做任何改变...怎么了?
我可以在有条件的情况下做.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
【问题讨论】:
为什么不直接检查 hasStopped 而不是使用本地的@State 属性? 我想过这个,但不记得我为什么改变主意了。您是否认为将isPlaying
替换为class
?按下按钮时我也会切换状态。
【参考方案1】:
您需要将ObservableObject
属性包装到ObservedObject
包装器中,以便跟踪已发布的属性,例如
struct SwiftUIView: View
@ObservedObject var speaker = Speaker() // << here !!
// @StateObject var speaker = Speaker() // << if single per view !!
【讨论】:
【参考方案2】:除了Asperi的回答你还需要设置Delegate:
override init()
super.init()
synth.delegate = self
【讨论】:
以上是关于如何在外部类中的事件后更新 SwiftUI 按钮?的主要内容,如果未能解决你的问题,请参考以下文章
如何在外部类上加载@ConfigurationProperties?