Publisher 中的 Publisher 不会触发 SwiftUi 重新渲染

Posted

技术标签:

【中文标题】Publisher 中的 Publisher 不会触发 SwiftUi 重新渲染【英文标题】:Publisher inside a Publisher does not trigger SwiftUi re-render 【发布时间】:2019-12-23 08:24:45 【问题描述】:

我在 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 按钮 self.isVisible.toggle() 触发 UI 更新,那么计数器也会更新。

如果不将计数器移动到视图中或在状态对象中实现它,我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

您的假设不正确。你将Counter 设为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
            )
        
    

【讨论】:

以上是关于Publisher 中的 Publisher 不会触发 SwiftUi 重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

dustindiaz&ŧ039;的Publisher类实现了javascript中的Publisher-subscriber模式

RabbitMQ - Publisher的消息确认机制

组合中的 Publisher 与 AnyPublisher

“Unknown Publisher”奇怪的证书问题

可以直接使用 Publisher 作为 SwiftUI 中的 @ObjectBinding 属性吗?

GA 到 BigQuery 导出架构中的“hits.publisher.adsRevenue”字段是啥意思?