swift - Publisher 中的 Publisher 不会触发 SwiftUi 重新渲染
问题描述
我在 EnvironmentObject 中为我的应用程序创建了一个“状态”对象,如下所示:
class AppState: ObservableObject {
@Published var counter = Counter()
}
要将其添加到我的应用程序中,我使用:
window.rootViewController = UIHostingController(rootView: contentView.environmentObject(state))
计数器是后台任务
class Counter: ObservableObject {
@Published var amount: Double
var timer = Timer()
init() {
self.amount = 0.0
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(setCoords), userInfo: nil, repeats: true)
}
@objc private func setCoords() {
DispatchQueue.main.async() { () -> Void in
self.amount = self.amount + 0.1
print(self.amount)
}
}
}
在我看来,我有:
struct ContentView: View {
@EnvironmentObject var state: AppState
@State var isVisible = true
var body: some View {
VStack {
Button(action: {
self.isVisible.toggle()
}) {
Text("Button")
}
if isVisible {
Text(state.counter.amount.description)
}
}
}
}
所以基本上,我希望每秒钟都能在我的 UI 更新中看到计数器。但是 UI 没有更新。我看到打印语句每秒触发一次,如果我从 UI 按钮触发 UI 更新,self.isVisible.toggle()
那么计数器也会更新。
如果不将计数器移动到视图中或在状态对象中实现它,我该如何解决这个问题?
解决方案
你的假设是不正确的。你做了Counter
as ObservableObject
,但从不观察它。
state
当@EnvironmentObject
你观察属性的变化时进行制作var counter
,但不是在它里面。它是类,引用类型,而不是结构,因此修改实例的内部属性不会导致修改实例本身 - 引用保持不变,因此state
不会改变。
这是使您的快照工作的方法之一 - 通过引入显式发布者事件来观察和更新相关的本地视图状态:
@State var currentCounter: String = ""
var body: some View {
VStack {
Button(action: {
self.isVisible.toggle()
}) {
Text("Button")
}
if isVisible {
Text(currentCounter)
.onReceive(state.counter.$amount, perform: { value in
self.currentCounter = value.description
})
}
}
}
推荐阅读
- vue.js - 如何在 v-textarea 中隐藏滚动条?
- python - RNN 带或不带循环:每个输出的含义?
- python - Cisco WebEx:使用 Python 2.7 为一组新令牌生成新代码时出现问题
- php - 如何在 laravel 版本 5.0.35 中配置任何 restful api 包,如 laravel/passort 或 dingo/api(*没有作曲家)
- html - 是否有任何 CSS 代码来定位图像,如下所示但也响应屏幕尺寸?
- python - 将 do-while 从 C 转换为 Python
- javascript - Knex await 如何执行数据库查询?
- c# - 从 IList 而不是 IEnumerable (C#) 获取数据
- hive - Hive 中的左连接未返回预期结果
- dart - 这两个变量的答案是什么?两者之间有什么区别?