【问题标题】:Timer onReceive not working inside NavigationView定时器 onReceive 在 NavigationView 中不起作用
【发布时间】:2020-04-23 03:16:33
【问题描述】:

我有以下计时器:

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 中更新它?还是有更好的做法?

谢谢

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

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

        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 中持久存在的视图,原因很可能是在条件 ViewBuilder 和围绕 UIKit UINavigationControler 的 NavigationView 包装器内部。

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

    如果在条件移除后它附加到Text("\(timeRemaining)") 那么一切正常(使用 Xcode 11.4 测试),因为在正文中存在状态依赖性。

    如果它附加到常量 Text 则正文没有任何变化,即。依赖于更改的状态 - timeRemaining,因此 SwiftUI 渲染引擎将 body 解释为静态。

    【讨论】:

    • 为什么会这样?我遇到了与 OP 相同的问题,这是一个有效的解决方案,但有助于理解原因。了解NavigationView 对此的影响也会有所帮助。删除条件并在单个Text 视图上使用onReceive,它仍然不起作用。
    • 我也遇到过同样的事情,不知道是什么原因。我发现计时器没有发布任何值。因为它被取消了一次。我已将第二个订阅者连接到计时器,但它没有获得任何价值或完成。但是,当我在 NavigationView 的外层空间调用 .onReceive 时,它​​的关闭和第二个订阅者都开始获取值。但是我仍然不知道为什么当我将.onReceive 放入 NavigationView 时会取消计时器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    • 1970-01-01
    • 2017-12-28
    • 1970-01-01
    相关资源
    最近更新 更多