Timer onReceive not working inside NavigationView

一曲冷凌霜 提交于 2020-12-29 07:41:11

问题


I have the following timer:

struct ContentView: View {
    @State var timeRemaining = 10
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        NavigationView{
            VStack {
                if(self.timeRemaining > 0) {
                    Text("\(timeRemaining)")
                        .onReceive(timer) { _ in
                            if self.timeRemaining > 0 {
                                self.timeRemaining -= 1
                            }
                    }
                } else {
                    Text("Time is up!")
                }
            }
        }
    }
}

If I remove the NavigationView view, the timer updates and works, but like that it doesn't, what's going on here and how can I update it while in the NavigationView? Or is there a better practice?

Thanks


回答1:


It is better to attach observers to non-conditional views, like

    var body: some View {
        NavigationView{
            VStack {
                if(self.timeRemaining > 0) {
                    Text("\(timeRemaining)")
                } else {
                    Text("Time is up!")
                }
            }
            .onReceive(timer) { _ in        // << to VStack
                if self.timeRemaining > 0 {
                    self.timeRemaining -= 1
                }
            }
        }
    }

Update: some thoughts added (of course SwiftUI internals are known only for Apple).

.onReceive must be attached to persistently present view in NavigationView, the reason is most probably in conditional ViewBuilder and internal of NavigationView wrapper around UIKit UINavigationControler.

if you remove the condition and have a single Text view with onReceive inside the VStack inside the NavigationView, nothing is ever received

If after condition removed it is attached to Text("\(timeRemaining)") then all works (tested with Xcode 11.4), because there is state dependency in body.

If it is attached to constant Text then there is nothing changed in body, ie. dependent on changed state - timeRemaining, so SwiftUI rendering engine interprets body as static.



来源:https://stackoverflow.com/questions/61378755/timer-onreceive-not-working-inside-navigationview

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!