计时器 onReceive 在 NavigationView 中不起作用 [英] Timer onReceive not working inside NavigationView

查看:29
本文介绍了计时器 onReceive 在 NavigationView 中不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下计时器:

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!")
                }
            }
        }
    }
}

如果我删除 NavigationView 视图,计时器会更新并工作,但就像它没有,这里发生了什么以及如何在 NavigationView 中更新它代码>?或者有更好的做法吗?

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?

谢谢

推荐答案

最好将观察者附加到非条件视图,例如

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
                }
            }
        }
    }

更新:添加了一些想法(当然,SwiftUI 内部结构仅适用于 Apple).

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

.onReceive 必须附加到 NavigationView 中持久存在的视图,原因很可能是在条件 ViewBuilder 和 UIKit UINavigationControler 周围的 NavigationView 包装器内部.

.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.

如果您删除条件并在 NavigationView 内的 VStack 内有一个带有 onReceive 的 Text 视图,则不会收到任何内容

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

如果条件删除后它被附加到 Text("\(timeRemaining)") 那么一切正常(用 Xcode 11.4 测试),因为主体中有状态依赖.

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.

如果它附加到常量 Text 则正文中没有任何变化,即.依赖于改变的状态 - timeRemaining,所以 SwiftUI 渲染引擎将 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.

这篇关于计时器 onReceive 在 NavigationView 中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆