导航到其他页面后,如何在 SwiftUI 中恢复已发布的计时器?

Posted

技术标签:

【中文标题】导航到其他页面后,如何在 SwiftUI 中恢复已发布的计时器?【英文标题】:How do I resume a published timer in SwiftUI after navigating to a different page? 【发布时间】:2020-03-27 14:57:54 【问题描述】:

在下面的 Playground 示例中,UI 正确地更新为当前日期,但是当导航离开页面并返回时,计时器不会继续计时:

  import SwiftUI
  import PlaygroundSupport

  struct MainTabView: View 
    let timer = Timer.publish(every: 1, on: .main, in: .common)

    @State var time = Date()

    var body: some View 
        TabView 
            VStack 
                Text("\(time)").onReceive(self.timer)  self.time = $0 
            
            .onAppear  _ = self.timer.connect() 
            .tabItem 
                Text("Page 1")
            

            Text("Page 2").tabItem 
                Text("Page 2")
            

            Text("Page 3").tabItem 
                Text("Page 3")
            
        
    


PlaygroundPage.current.setLiveView(MainTabView())

如何让计时器在页面开始显示时再次开始更新?

我见过涉及将 Timer 包装在另一个类中的解决方案,但在 View 中无法完成。

我认为在onAppear 中调用connect() 就可以了。

【问题讨论】:

【参考方案1】:

在 onAppear 中重新初始化你的计时器和日期会起作用:

struct ContentView: View 
    @State private var timer = Timer.publish(every: 1, on: .main, in: .common)
    @State var time = Date()

    var body: some View 
        TabView 
            VStack 
                Text("\(time)").onReceive(self.timer)  self.time = $0 
            
            .onAppear(perform: 
                self.time = Date()
                self.timer = Timer.publish(every: 1, on: .main, in: .common)
                _ = self.timer.connect()
            )
            .tabItem 
                Text("Page 1")
            

            Text("Page 2").tabItem 
                Text("Page 2")
            

            Text("Page 3").tabItem 
                Text("Page 3")
            
        
    

【讨论】:

【参考方案2】:

当没有更多订阅者时,定时器被取消,当定时器被取消时,它不能再次启动......所以你需要在每次选择第一个选项卡时不取消定时器或重新创建定时器。

这是可能的解决方案(案例 1,使用 Xcode 11.4 测试)

struct MainTabView: View 
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    @State var time = Date()

    var body: some View 
        TabView 
            VStack 
                Text("\(time)")
            
                .tabItem 
                    Text("Page 1")
            

            Text("Page 2").tabItem 
                Text("Page 2")
            

            Text("Page 3").tabItem 
                Text("Page 3")
            
        .onReceive(self.timer)  self.time = $0  // here !!
    

【讨论】:

以上是关于导航到其他页面后,如何在 SwiftUI 中恢复已发布的计时器?的主要内容,如果未能解决你的问题,请参考以下文章

使用 SwiftUI 成功登录后导航

网页导航被取消该怎么恢复

如何使用滚动视图单击列表部分内的项目以导航到详细信息页面 SwiftUI

iOS14中点击SwiftUI列表项导航跳转返回后外观呈灰色的解决

为 SwiftUI Apple Watch App 实现基于页面的导航

在页面之间导航后如何在jquery mobile中停止重复数据