swift - 计时器 onReceive 在 NavigationView 中不起作用

标签 swift swiftui

我有以下计时器:

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 View ,计时器会更新并工作,但就像那样它不会,这里发生了什么以及我如何在 NavigationView?或者有更好的做法吗?

谢谢

最佳答案

最好将观察者附加到非条件 View ,比如

    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 使用)。

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

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 测试),因为主体中存在状态依赖性。

如果它附加到常量文本,那么主体没有任何变化,即。依赖于变化的状态 - timeRemaining,因此 SwiftUI 渲染引擎将 body 解释为静态。

关于swift - 计时器 onReceive 在 NavigationView 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61378755/

相关文章:

swift - 将字符串转换为 Bool 并在 Swift 中测试 IF 语句

ios - 如何在 iOS 图表的 X 轴上添加字符串?

Swift - 如何从 View 之外的函数访问@Published var?

animation - SwiftUI ViewModifier 动画每次都无法正确显示

swift - 带条件的@IBSegueAction

ios - 应用程序启动时 NSUserDefaults 的值不一致

ios - 如何将 SCNCamera 看到的内容渲染到平面上?

iOS 在两个导航 Controller 之间切换

swift - 如何在 SwiftUI 中根据其子项高度设置 GeometryReader 高度?

SwiftUI:在 Text 之间添加仅 1 的填充会创建一个巨大的填充 - 如何实际制作一个小填充?